Subject: Why mark our .note.netbsd signature LOADable?
To: None <tech-toolchain@NetBSD.org>
From: Martin Husemann <martin@duskware.de>
List: tech-toolchain
Date: 12/06/2006 14:44:44
--NzB8fVQJ5HfG6fxh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

After playing with .note sections to mark the kernel as a NetBSD binary
yesterday, I commited a change to the .note section generating code
for the kernel. At this time I was a bit confused, and did not fully 
understand what this caused.

When thinking about it later, I wondered if we should do the same change to
the userland .note section. A patch that does this, and also changes 
exec_elf32.c to cope with it is attached.

I am not sure we want to do this - so let me try to explain the change:

What is the difference?

Our current note mark is a PT_NOTE PHDR:

    NOTE off    0x00000000000001a4 vaddr 0x00000000001001a4 paddr 0x00000000001001a4 align 2**2
         filesz 0x0000000000000018 memsz 0x0000000000000018 flags r--

It creates a SHT_NOTE section too:

  1 .note.netbsd.ident 00000018  00000000001001a4  00000000001001a4  000001a4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA


Since this note is only used to mark our binaries, it is something that is not
needed after starting the binary, so for one the LOAD flag is not needed, IMHO.
Neither is the ALLOC or DATA.

So, with the same change I did to the kernel note section done to userland,
this all ends up without a PT_NOTE phdr, but only a simple SHT_NOTE section:

# objdump -p /bin/ls 

/bin/ls:     file format elf64-sparc

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000100040 paddr 0x0000000000100040 align 2**3
         filesz 0x0000000000000118 memsz 0x0000000000000118 flags r-x
  INTERP off    0x0000000000000158 vaddr 0x0000000000100158 paddr 0x0000000000100158 align 2**0
         filesz 0x0000000000000013 memsz 0x0000000000000013 flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000100000 paddr 0x0000000000100000 align 2**20
         filesz 0x0000000000004fe4 memsz 0x0000000000004fe4 flags r-x
    LOAD off    0x0000000000004fe8 vaddr 0x0000000000204fe8 paddr 0x0000000000204fe8 align 2**20
         filesz 0x00000000000009d4 memsz 0x0000000000000d20 flags rwx
 DYNAMIC off    0x0000000000005010 vaddr 0x0000000000205010 paddr 0x0000000000205010 align 2**3
         filesz 0x0000000000000190 memsz 0x0000000000000190 flags rw-

Dynamic Section:
  NEEDED      libc.so.12
  RPATH       /lib
  INIT        0x101130
  FINI        0x104d40
  HASH        0x100170
  STRTAB      0x100948
  SYMTAB      0x100318
  STRSZ       0x260
  SYMENT      0x18
  DEBUG       0x0
  PLTGOT      0x205300
  PLTRELSZ    0x480
  PLTREL      0x7
  JMPREL      0x100cb0
  RELA        0x100ba8
  RELASZ      0x588
  RELAENT     0x18
  0x70000001  0x1
  0x70000001  0x2

and still a SHT_NOTE section:

# objdump -h /bin/ls 

/bin/ls:     file format elf64-sparc

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
[...]
 21 .note.netbsd.ident 00000018  0000000000000000  0000000000000000  00005df0  2**2
                  CONTENTS, READONLY

a slightly older file(1) is still happy with this (-current file(1) looks
broken again, but that is probably unrelated), and gdb seems to be fine
too:

# gdb
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc64--netbsd".
(gdb) set debug arch 1
(gdb) file /bin/ls
find_arch_by_info: info.bfd_arch_info sparc:v9
find_arch_by_info: info.byte_order 0 (big)
find_arch_by_info: info.osabi 9 (NetBSD ELF)
find_arch_by_info: info.abfd 0x4f2c00
find_arch_by_info: info.tdep_info 0x0

... but then I can't test gdb for real, because currently PTRACE seems to
be broken.

Do we want this change?

Martin

--NzB8fVQJ5HfG6fxh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch

Index: libexec/ld.elf_so/sysident.h
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/sysident.h,v
retrieving revision 1.13
diff -u -p -r1.13 sysident.h
--- libexec/ld.elf_so/sysident.h	13 Jun 2006 13:55:58 -0000	1.13
+++ libexec/ld.elf_so/sysident.h	6 Dec 2006 13:24:41 -0000
@@ -63,7 +63,7 @@
 
 #define	__S(x)	__STRING(x)
 __asm(
-	".section\t\".note.netbsd.ident\", \"a\"\n"
+	".section\t\".note.netbsd.ident\", \"\",@note\n"
 	"\t.p2align\t2\n\n"
 
 	"\t.long\t" __S(ELF_NOTE_NETBSD_NAMESZ) "\n"
Index: sys/kern/exec_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/kern/exec_elf32.c,v
retrieving revision 1.120
diff -u -p -r1.120 exec_elf32.c
--- sys/kern/exec_elf32.c	24 Nov 2006 01:13:11 -0000	1.120
+++ sys/kern/exec_elf32.c	6 Dec 2006 13:24:41 -0000
@@ -119,6 +119,7 @@ int	netbsd_elf_probe(struct lwp *, struc
 #define	ELF_TRUNC(a, b)		((a) & ~((b) - 1))
 
 #define MAXPHNUM	50
+#define	MAXSHNUM	1000
 
 /*
  * Copy arguments onto the stack in the normal way, but add some
@@ -761,11 +762,13 @@ netbsd_elf_signature(struct lwp *l, stru
     Elf_Ehdr *eh)
 {
 	size_t i;
-	Elf_Phdr *ph;
-	size_t phsize;
+	Elf_Phdr *ph = NULL;
+	Elf_Shdr *sh = NULL;
+	Elf_Nhdr *np = NULL;
+	size_t phsize, shsize;
 	int error;
 
-	if (eh->e_phnum > MAXPHNUM)
+	if (eh->e_phnum > MAXPHNUM || eh->e_shnum > MAXSHNUM)
 		return ENOEXEC;
 
 	phsize = eh->e_phnum * sizeof(Elf_Phdr);
@@ -773,10 +776,43 @@ netbsd_elf_signature(struct lwp *l, stru
 	error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize);
 	if (error)
 		goto out;
+	shsize = eh->e_shnum * sizeof(Elf_Shdr);
+	sh = (Elf_Shdr *)malloc(shsize, M_TEMP, M_WAITOK);
+	error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
+	if (error)
+		goto out;
+
+	for (i = 0; i < eh->e_shnum; i++) {
+		Elf_Shdr *shp = &sh[i];
+
+		if (shp->sh_type != SHT_NOTE ||
+		    shp->sh_size > 1024 ||
+		    shp->sh_size < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
+			continue;
+
+		np = (Elf_Nhdr *)malloc(shp->sh_size, M_TEMP, M_WAITOK);
+		error = exec_read_from(l, epp->ep_vp, shp->sh_offset, np,
+		    shp->sh_size);
+		if (error)
+			goto next1;
 
+		if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG ||
+		    np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
+		    np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
+		    memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME,
+		    ELF_NOTE_NETBSD_NAMESZ))
+			goto next1;
+
+		error = 0;
+		free(np, M_TEMP);
+		goto out;
+
+	next1:
+		free(np, M_TEMP);
+		continue;
+	}
 	for (i = 0; i < eh->e_phnum; i++) {
 		Elf_Phdr *ephp = &ph[i];
-		Elf_Nhdr *np;
 
 		if (ephp->p_type != PT_NOTE ||
 		    ephp->p_filesz > 1024 ||
@@ -787,27 +823,28 @@ netbsd_elf_signature(struct lwp *l, stru
 		error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np,
 		    ephp->p_filesz);
 		if (error)
-			goto next;
+			goto next2;
 
 		if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG ||
 		    np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
 		    np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
 		    memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME,
 		    ELF_NOTE_NETBSD_NAMESZ))
-			goto next;
+			goto next2;
 
 		error = 0;
 		free(np, M_TEMP);
 		goto out;
 
-	next:
+	next2:
 		free(np, M_TEMP);
 		continue;
 	}
 
 	error = ENOEXEC;
 out:
-	free(ph, M_TEMP);
+	if (ph) free(ph, M_TEMP);
+	if (sh) free(sh, M_TEMP);
 	return error;
 }
 

--NzB8fVQJ5HfG6fxh--