From c8451af8ab0c2e2a93ce93b9c68257d31576cc85 Mon Sep 17 00:00:00 2001 From: Christos Zoulas Date: Tue, 5 Nov 2013 15:44:01 +0000 Subject: [PATCH] - split netbsd and freebsd version printing into separate functions - don't let the NetBSD pax note end the search for notes - add 2 more NetBSD notes --- src/readelf.c | 262 ++++++++++++++++++++++++++++---------------------- src/readelf.h | 23 +++++ 2 files changed, 169 insertions(+), 116 deletions(-) diff --git a/src/readelf.c b/src/readelf.c index ebaf0936..2bb32aa8 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readelf.c,v 1.97 2013/03/06 03:35:30 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.98 2013/09/20 00:39:43 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -344,6 +344,126 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } #endif +static void +do_note_netbsd_version(struct magic_set *ms, int swap, void *v) +{ + uint32_t desc; + (void)memcpy(&desc, v, sizeof(desc)); + desc = elf_getu32(swap, desc); + + if (file_printf(ms, ", for NetBSD") == -1) + return; + /* + * The version number used to be stuck as 199905, and was thus + * basically content-free. Newer versions of NetBSD have fixed + * this and now use the encoding of __NetBSD_Version__: + * + * MMmmrrpp00 + * + * M = major version + * m = minor version + * r = release ["",A-Z,Z[A-Z] but numeric] + * p = patchlevel + */ + if (desc > 100000000U) { + uint32_t ver_patch = (desc / 100) % 100; + uint32_t ver_rel = (desc / 10000) % 100; + uint32_t ver_min = (desc / 1000000) % 100; + uint32_t ver_maj = desc / 100000000; + + if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1) + return; + if (ver_rel == 0 && ver_patch != 0) { + if (file_printf(ms, ".%u", ver_patch) == -1) + return; + } else if (ver_rel != 0) { + while (ver_rel > 26) { + if (file_printf(ms, "Z") == -1) + return; + ver_rel -= 26; + } + if (file_printf(ms, "%c", 'A' + ver_rel - 1) + == -1) + return; + } + } +} + +static void +do_note_freebsd_version(struct magic_set *ms, int swap, void *v) +{ + uint32_t desc; + + (void)memcpy(&desc, v, sizeof(desc)); + desc = elf_getu32(swap, desc); + if (file_printf(ms, ", for FreeBSD") == -1) + return; + + /* + * Contents is __FreeBSD_version, whose relation to OS + * versions is defined by a huge table in the Porter's + * Handbook. This is the general scheme: + * + * Releases: + * Mmp000 (before 4.10) + * Mmi0p0 (before 5.0) + * Mmm0p0 + * + * Development branches: + * Mmpxxx (before 4.6) + * Mmp1xx (before 4.10) + * Mmi1xx (before 5.0) + * M000xx (pre-M.0) + * Mmm1xx + * + * M = major version + * m = minor version + * i = minor version increment (491000 -> 4.10) + * p = patchlevel + * x = revision + * + * The first release of FreeBSD to use ELF by default + * was version 3.0. + */ + if (desc == 460002) { + if (file_printf(ms, " 4.6.2") == -1) + return; + } else if (desc < 460100) { + if (file_printf(ms, " %d.%d", desc / 100000, + desc / 10000 % 10) == -1) + return; + if (desc / 1000 % 10 > 0) + if (file_printf(ms, ".%d", desc / 1000 % 10) == -1) + return; + if ((desc % 1000 > 0) || (desc % 100000 == 0)) + if (file_printf(ms, " (%d)", desc) == -1) + return; + } else if (desc < 500000) { + if (file_printf(ms, " %d.%d", desc / 100000, + desc / 10000 % 10 + desc / 1000 % 10) == -1) + return; + if (desc / 100 % 10 > 0) { + if (file_printf(ms, " (%d)", desc) == -1) + return; + } else if (desc / 10 % 10 > 0) { + if (file_printf(ms, ".%d", desc / 10 % 10) == -1) + return; + } + } else { + if (file_printf(ms, " %d.%d", desc / 100000, + desc / 1000 % 100) == -1) + return; + if ((desc / 100 % 10 > 0) || + (desc % 100000 / 100 == 0)) { + if (file_printf(ms, " (%d)", desc) == -1) + return; + } else if (desc / 10 % 10 > 0) { + if (file_printf(ms, ".%d", desc / 10 % 10) == -1) + return; + } + } +} + private size_t donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, int clazz, int swap, size_t align, int *flags) @@ -488,131 +608,41 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, pax[i]) == -1) return size; } - *flags |= FLAGS_DID_BUILD_ID; } - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0 && - xnh_type == NT_NETBSD_VERSION && descsz == 4) { - uint32_t desc; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); - desc = elf_getu32(swap, desc); - - if (file_printf(ms, ", for NetBSD") == -1) - return size; - /* - * The version number used to be stuck as 199905, and was thus - * basically content-free. Newer versions of NetBSD have fixed - * this and now use the encoding of __NetBSD_Version__: - * - * MMmmrrpp00 - * - * M = major version - * m = minor version - * r = release ["",A-Z,Z[A-Z] but numeric] - * p = patchlevel - */ - if (desc > 100000000U) { - uint32_t ver_patch = (desc / 100) % 100; - uint32_t ver_rel = (desc / 10000) % 100; - uint32_t ver_min = (desc / 1000000) % 100; - uint32_t ver_maj = desc / 100000000; - - if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1) + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + switch (xnh_type) { + case NT_NETBSD_VERSION: + if (descsz == 4) { + do_note_netbsd_version(ms, swap, &nbuf[doff]); + *flags |= FLAGS_DID_NOTE; return size; - if (ver_rel == 0 && ver_patch != 0) { - if (file_printf(ms, ".%u", ver_patch) == -1) - return size; - } else if (ver_rel != 0) { - while (ver_rel > 26) { - if (file_printf(ms, "Z") == -1) - return size; - ver_rel -= 26; - } - if (file_printf(ms, "%c", 'A' + ver_rel - 1) - == -1) - return size; } + break; + case NT_NETBSD_MARCH: + if (file_printf(ms, ", compiled for: %.*s", (int)descsz, + (const char *)&nbuf[doff]) == -1) + return size; + break; + case NT_NETBSD_CMODEL: + if (file_printf(ms, ", compiler model: %.*s", + (int)descsz, (const char *)&nbuf[doff]) == -1) + return size; + break; + default: + if (file_printf(ms, ", note=%u", xnh_type) == -1) + return size; + break; } - *flags |= FLAGS_DID_NOTE; return size; } - if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0 && - xnh_type == NT_FREEBSD_VERSION && descsz == 4) { - uint32_t desc; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); - desc = elf_getu32(swap, desc); - if (file_printf(ms, ", for FreeBSD") == -1) + if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { + if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) { + do_note_freebsd_version(ms, swap, &nbuf[doff]); + *flags |= FLAGS_DID_NOTE; return size; - - /* - * Contents is __FreeBSD_version, whose relation to OS - * versions is defined by a huge table in the Porter's - * Handbook. This is the general scheme: - * - * Releases: - * Mmp000 (before 4.10) - * Mmi0p0 (before 5.0) - * Mmm0p0 - * - * Development branches: - * Mmpxxx (before 4.6) - * Mmp1xx (before 4.10) - * Mmi1xx (before 5.0) - * M000xx (pre-M.0) - * Mmm1xx - * - * M = major version - * m = minor version - * i = minor version increment (491000 -> 4.10) - * p = patchlevel - * x = revision - * - * The first release of FreeBSD to use ELF by default - * was version 3.0. - */ - if (desc == 460002) { - if (file_printf(ms, " 4.6.2") == -1) - return size; - } else if (desc < 460100) { - if (file_printf(ms, " %d.%d", desc / 100000, - desc / 10000 % 10) == -1) - return size; - if (desc / 1000 % 10 > 0) - if (file_printf(ms, ".%d", desc / 1000 % 10) - == -1) - return size; - if ((desc % 1000 > 0) || (desc % 100000 == 0)) - if (file_printf(ms, " (%d)", desc) == -1) - return size; - } else if (desc < 500000) { - if (file_printf(ms, " %d.%d", desc / 100000, - desc / 10000 % 10 + desc / 1000 % 10) == -1) - return size; - if (desc / 100 % 10 > 0) { - if (file_printf(ms, " (%d)", desc) == -1) - return size; - } else if (desc / 10 % 10 > 0) { - if (file_printf(ms, ".%d", desc / 10 % 10) - == -1) - return size; - } - } else { - if (file_printf(ms, " %d.%d", desc / 100000, - desc / 1000 % 100) == -1) - return size; - if ((desc / 100 % 10 > 0) || - (desc % 100000 / 100 == 0)) { - if (file_printf(ms, " (%d)", desc) == -1) - return size; - } else if (desc / 10 % 10 > 0) { - if (file_printf(ms, ".%d", desc / 10 % 10) - == -1) - return size; - } } - *flags |= FLAGS_DID_NOTE; - return size; } if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && diff --git a/src/readelf.h b/src/readelf.h index 10a9e636..732b20c8 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -272,6 +272,29 @@ typedef struct { #define NT_NETBSD_PAX_ASLR 0x10 /* Force enable ASLR */ #define NT_NETBSD_PAX_NOASLR 0x20 /* Force disable ASLR */ +/* + * NetBSD-specific note type: MACHINE_ARCH. + * There should be 1 NOTE per executable. + * name: NetBSD\0 + * namesz: 7 + * desc: string + * descsz: variable + */ +#define NT_NETBSD_MARCH 5 + +/* + * NetBSD-specific note type: COMPILER MODEL. + * There should be 1 NOTE per executable. + * name: NetBSD\0 + * namesz: 7 + * desc: string + * descsz: variable + */ +#define NT_NETBSD_CMODEL 6 + +#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE) +#define ELFSIZE ARCH_ELFSIZE +#endif /* SunOS 5.x hardware/software capabilities */ typedef struct { Elf32_Word c_tag; -- 2.50.0