NT_VERSION notes are emitted by the gas .version directive. They have an empty description and (ab)use the owner name to store the version data string.
Signed-off-by: Mark Wielaard <m...@klomp.org> --- libebl/ChangeLog | 9 +++++++++ libebl/eblobjnote.c | 10 +++++++++- libebl/eblobjnotetypename.c | 8 +++++++- libebl/libebl.h | 4 ++-- src/ChangeLog | 7 +++++++ src/elflint.c | 27 +++++++++++++++++++++------ src/readelf.c | 1 + tests/ChangeLog | 5 +++++ tests/run-readelf-n.sh | 19 ++++++++++++++++++- 9 files changed, 79 insertions(+), 11 deletions(-) diff --git a/libebl/ChangeLog b/libebl/ChangeLog index 120c84c06..076596f09 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,3 +1,12 @@ +2018-11-11 Mark Wielaard <m...@klomp.org> + + * eblobjnote.c (ebl_object_note): Recognize NT_VERSION with zero + descriptor. Add explicit "GNU" name check. + * eblobjnotetypename.c (ebl_object_note_type_name): Add extra + argument descsz. Recognize NT_VERSION using descsz. With "GNU" + name it is NT_GNU_ABI_TAG. + * libebl.h (ebl_object_note_type_name): Add extra argument descsz. + 2018-10-18 Mark Wielaard <m...@klomp.org> * eblobjnote.c (ebl_object_note): Handle NT_GNU_PROPERTY_TYPE_0. diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c index 57e9f52f4..8fda7d992 100644 --- a/libebl/eblobjnote.c +++ b/libebl/eblobjnote.c @@ -135,6 +135,14 @@ ebl_object_note (Ebl *ebl, const char *name, uint32_t type, return; } + /* NT_VERSION doesn't have any info. All data is in the name. */ + if (descsz == 0 && type == NT_VERSION) + return; + + /* Everything else should have the "GNU" owner name. */ + if (strcmp ("GNU", name) != 0) + return; + switch (type) { case NT_GNU_BUILD_ID: @@ -337,7 +345,7 @@ ebl_object_note (Ebl *ebl, const char *name, uint32_t type, break; case NT_GNU_ABI_TAG: - if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0) + if (descsz >= 8 && descsz % 4 == 0) { Elf_Data in = { diff --git a/libebl/eblobjnotetypename.c b/libebl/eblobjnotetypename.c index af23caea8..8cdd78199 100644 --- a/libebl/eblobjnotetypename.c +++ b/libebl/eblobjnotetypename.c @@ -39,6 +39,7 @@ const char * ebl_object_note_type_name (Ebl *ebl, const char *name, uint32_t type, + GElf_Word descsz, char *buf, size_t len) { const char *res = ebl->object_note_type_name (name, type, buf, len); @@ -80,14 +81,19 @@ ebl_object_note_type_name (Ebl *ebl, const char *name, uint32_t type, if (strcmp (name, "GNU") != 0) { + /* NT_VERSION is special, all data is in the name. */ + if (descsz == 0 && type == NT_VERSION) + return "VERSION"; + snprintf (buf, len, "%s: %" PRIu32, gettext ("<unknown>"), type); return buf; } + /* And finally all the "GNU" note types. */ static const char *knowntypes[] = { #define KNOWNSTYPE(name) [NT_##name] = #name - KNOWNSTYPE (VERSION), + KNOWNSTYPE (GNU_ABI_TAG), KNOWNSTYPE (GNU_HWCAP), KNOWNSTYPE (GNU_BUILD_ID), KNOWNSTYPE (GNU_GOLD_VERSION), diff --git a/libebl/libebl.h b/libebl/libebl.h index a34fe48dd..583065475 100644 --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -175,8 +175,8 @@ extern const char *ebl_core_note_type_name (Ebl *ebl, uint32_t type, char *buf, /* Return name of the note section type for an object file. */ extern const char *ebl_object_note_type_name (Ebl *ebl, const char *name, - uint32_t type, char *buf, - size_t len); + uint32_t type, GElf_Word descsz, + char *buf, size_t len); /* Print information about object note if available. */ extern void ebl_object_note (Ebl *ebl, const char *name, uint32_t type, diff --git a/src/ChangeLog b/src/ChangeLog index fc6d414ff..9f26b259a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2018-11-11 Mark Wielaard <m...@klomp.org> + + * readelf.c (handle_notes_data): Pass n_descsz to + ebl_object_note_type_name. + * elflint.c (check_note_data): Recognize NT_VERSION, add owner + name to unknown note error. + 2018-11-10 Mark Wielaard <m...@klomp.org> * elflint.c (check_program_header): Allow PT_GNU_EH_FRAME segment diff --git a/src/elflint.c b/src/elflint.c index 658f2ae2c..bddb8dd8e 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -1,5 +1,5 @@ /* Pedantic checking of ELF files compliance with gABI/psABI spec. - Copyright (C) 2001-2015, 2017 Red Hat, Inc. + Copyright (C) 2001-2015, 2017, 2018 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <drep...@redhat.com>, 2001. @@ -4332,7 +4332,17 @@ section [%2d] '%s': unknown core file note type %" PRIu32 case NT_GNU_BUILD_ID: case NT_GNU_GOLD_VERSION: case NT_GNU_PROPERTY_TYPE_0: - break; + if (nhdr.n_namesz == sizeof ELF_NOTE_GNU + && strcmp (data->d_buf + name_offset, ELF_NOTE_GNU) == 0) + break; + else + { + /* NT_VERSION is 1, same as NT_GNU_ABI_TAG. It has no + descriptor and (ab)uses the name as version string. */ + if (nhdr.n_descsz == 0 && nhdr.n_type == NT_VERSION) + break; + } + goto unknown_note; case 0: /* Linux vDSOs use a type 0 note for the kernel version word. */ @@ -4341,16 +4351,21 @@ section [%2d] '%s': unknown core file note type %" PRIu32 break; FALLTHROUGH; default: + { + unknown_note: if (shndx == 0) ERROR (gettext ("\ -phdr[%d]: unknown object file note type %" PRIu32 " at offset %zu\n"), - phndx, (uint32_t) nhdr.n_type, offset); +phdr[%d]: unknown object file note type %" PRIu32 " with owner name '%s' at offset %zu\n"), + phndx, (uint32_t) nhdr.n_type, + (char *) data->d_buf + name_offset, offset); else ERROR (gettext ("\ section [%2d] '%s': unknown object file note type %" PRIu32 - " at offset %zu\n"), + " with owner name '%s' at offset %zu\n"), shndx, section_name (ebl, shndx), - (uint32_t) nhdr.n_type, offset); + (uint32_t) nhdr.n_type, + (char *) data->d_buf + name_offset, offset); + } } } diff --git a/src/readelf.c b/src/readelf.c index c6c3fb323..659e34fb5 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -12201,6 +12201,7 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, ? ebl_core_note_type_name (ebl, nhdr.n_type, buf, sizeof (buf)) : ebl_object_note_type_name (ebl, name, nhdr.n_type, + nhdr.n_descsz, buf2, sizeof (buf2))); /* Filter out invalid entries. */ diff --git a/tests/ChangeLog b/tests/ChangeLog index 92dfb95d7..d92b8e3ac 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2018-11-11 Mark Wielaard <m...@klomp.org> + + * run-readelf-n.sh: Fix NT_GNU_ABI_TAG type. Add testfile11 test + for NT_VERSION. + 2018-11-04 Mark Wielaard <m...@klomp.org> * testfile-bpf-reloc.expect.bz2: Update with new expected jump diff --git a/tests/run-readelf-n.sh b/tests/run-readelf-n.sh index 3ae7cf02f..7e2a845e6 100755 --- a/tests/run-readelf-n.sh +++ b/tests/run-readelf-n.sh @@ -48,8 +48,25 @@ Note segment of 32 bytes at offset 0x300: Note segment of 68 bytes at offset 0x320: Owner Data size Type - GNU 16 VERSION + GNU 16 GNU_ABI_TAG OS: Linux, ABI: 3.2.0 GNU 20 GNU_BUILD_ID Build ID: 83cb2229fabd2065d1361f5b46424cd75270f94b EOF + +# NT_VERSION note type clashes with "GNU" owner type NT_GNU_ABI_TAG. +# Uses owner name (with zero desc) for version string. +testfiles testfile11 +testrun_compare ${abs_top_builddir}/src/readelf -n testfile11 << EOF + +Note section [ 2] '.note.ABI-tag' of 32 bytes at offset 0x128: + Owner Data size Type + GNU 16 GNU_ABI_TAG + OS: Linux, ABI: 2.2.5 + +Note section [35] '.note' of 60 bytes at offset 0x13364: + Owner Data size Type + 01.01 0 VERSION + 01.01 0 VERSION + 01.01 0 VERSION +EOF -- 2.19.1