Subject: file(1) patch to recognise ELF notes in executables
To: None <tech-userlevel@netbsd.org>
From: Ben Harris <bjh21@netbsd.org>
List: tech-userlevel
Date: 03/07/2002 19:46:12
This patch is intended as a partial fix for PR bin/12295, which points out
that file(1)'s output for ELF executables doesn't mention which OS they're
for. It recognises both NetBSD and GNU executables, and produces output
like:
/usr/bin/printf: ELF 32-bit MSB executable, PowerPC or cisco 4500, version
1, for NetBSD, dynamically linked (uses shared libs), stripped
/opt/netbsd/citrix_ica/linuxarm/echo_cmd: ELF 32-bit LSB executable,
Advanced RISC Machines ARM, version 1, for GNU/Linux 2.0.0, dynamically
linked (uses shared libs), stripped
Any comments? If not, I'll probably commit it myself.
Index: readelf.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/file/readelf.c,v
retrieving revision 1.10
diff -u -u -r1.10 readelf.c
--- readelf.c 2001/12/09 23:21:07 1.10
+++ readelf.c 2002/03/07 19:37:49
@@ -177,9 +177,14 @@
size_t size;
{
Elf32_Phdr ph32;
+ Elf32_Nhdr *nh32;
Elf64_Phdr ph64;
+ Elf64_Nhdr *nh64;
char *linking_style = "statically";
char *shared_libraries = "";
+ char nbuf[BUFSIZ];
+ int bufsize;
+ size_t offset, nameoffset;
if (lseek(fd, off, SEEK_SET) == -1)
error("lseek failed (%s).\n", strerror(errno));
@@ -194,6 +199,80 @@
break;
case PT_INTERP:
shared_libraries = " (uses shared libs)";
+ break;
+ case PT_NOTE:
+ /*
+ * This is a PT_NOTE section; loop through all the notes
+ * in the section.
+ */
+ if (lseek(fd, (off_t) ph_offset, SEEK_SET) == -1)
+ error("lseek failed (%s).\n", strerror(errno));
+ bufsize = read(fd, nbuf, BUFSIZ);
+ if (bufsize == -1)
+ error(": " "read failed (%s).\n",
+ strerror(errno));
+ offset = 0;
+ for (;;) {
+ if (offset >= bufsize)
+ break;
+ if (class == ELFCLASS32)
+ nh32 = (Elf32_Nhdr *)&nbuf[offset];
+ else
+ nh64 = (Elf64_Nhdr *)&nbuf[offset];
+ offset += nh_size;
+
+ if (offset + nh_namesz >= bufsize) {
+ /*
+ * We're past the end of the buffer.
+ */
+ break;
+ }
+
+ nameoffset = offset;
+ offset += nh_namesz;
+ offset = ((offset + 3)/4)*4;
+
+ if (offset + nh_descsz >= bufsize)
+ break;
+
+ if (nh_namesz == 4 &&
+ strcmp(&nbuf[nameoffset], "GNU") == 0 &&
+ nh_type == NT_GNU_VERSION &&
+ nh_descsz == 16) {
+ uint32_t *desc =
+ (uint32_t *)&nbuf[offset];
+
+ printf(", for GNU/");
+ switch (getu32(swap, desc[0])) {
+ case GNU_OS_LINUX:
+ printf("Linux");
+ break;
+ case GNU_OS_HURD:
+ printf("Hurd");
+ break;
+ case GNU_OS_SOLARIS:
+ printf("Solaris");
+ break;
+ default:
+ printf("<unknown>");
+ }
+ printf(" %d.%d.%d",
+ getu32(swap, desc[1]),
+ getu32(swap, desc[2]),
+ getu32(swap, desc[3]));
+ }
+
+ if (nh_namesz == 7 &&
+ strcmp(&nbuf[nameoffset], "NetBSD") == 0 &&
+ nh_type == NT_NETBSD_VERSION &&
+ nh_descsz == 4) {
+ printf(", for NetBSD");
+ /*
+ * Version number is stuck at 199905,
+ * and hence is basically content-free.
+ */
+ }
+ }
break;
}
}
Index: readelf.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/file/readelf.h,v
retrieving revision 1.6
diff -u -u -r1.6 readelf.h
--- readelf.h 2001/12/09 23:21:07 1.6
+++ readelf.h 2002/03/07 19:37:49
@@ -190,4 +190,16 @@
#define NT_PLATFORM 5
#define NT_AUXV 6
+/* Note types used in executables */
+/* NetBSD executables (name = "NetBSD") */
+#define NT_NETBSD_VERSION 1
+#define NT_NETBSD_EMULATION 2
+/* GNU executables (name = "GNU") */
+#define NT_GNU_VERSION 1
+
+/* GNU OS tags */
+#define GNU_OS_LINUX 0
+#define GNU_OS_HURD 1
+#define GNU_OS_SOLARIS 2
+
#endif
--
Ben Harris <bjh21@netbsd.org>
Portmaster, NetBSD/arm26 <URL:http://www.netbsd.org/Ports/arm26/>