From: Timm Bäder <tbae...@redhat.com> Signed-off-by: Timm Bäder <tbae...@redhat.com> --- libdwfl/dwfl_segment_report_module.c | 187 +++++++++++++++------------ 1 file changed, 101 insertions(+), 86 deletions(-)
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 6abbf992..6c6f9f37 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -282,6 +282,99 @@ read_portion (Dwfl *dwfl, return false; } + +/* Consider a PT_NOTE we've found in the image. */ +static inline void +consider_notes (Dwfl *dwfl, + Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg, + GElf_Addr vaddr, GElf_Xword filesz, + GElf_Xword align, + void *buffer, size_t buffer_available, + GElf_Addr start, + size_t segment, + unsigned char ei_data, + struct elf_build_id *build_id, + Elf_Data *xlatefrom, + Elf_Data *xlateto, + unsigned int xencoding) +{ + if (build_id->memory != NULL || filesz == 0) + return; + + void *data; + size_t data_size; + if (read_portion (dwfl, memory_callback, memory_callback_arg, + &data, &data_size, vaddr, filesz, + buffer, buffer_available, start, segment)) + return; + + /* data_size will be zero if we got everything from the initial + buffer, otherwise it will be the size of the new buffer that + could be read. */ + if (data_size != 0) + filesz = data_size; + + assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); + + void *notes; + if (ei_data == MY_ELFDATA) + notes = data; + else + { + notes = malloc (filesz); + if (unlikely (notes == NULL)) + return; + xlatefrom->d_type = xlateto->d_type = (align == 8 + ? ELF_T_NHDR8 : ELF_T_NHDR); + xlatefrom->d_buf = (void *) data; + xlatefrom->d_size = filesz; + xlateto->d_buf = notes; + xlateto->d_size = filesz; + if (elf32_xlatetom (xlateto, xlatefrom, xencoding) == NULL) + goto done; + } + + const GElf_Nhdr *nh = notes; + size_t len = 0; + while (filesz > len + sizeof (*nh)) + { + const void *note_name; + const void *note_desc; + + len += sizeof (*nh); + note_name = notes + len; + + len += nh->n_namesz; + len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len); + note_desc = notes + len; + + if (unlikely (filesz < len + nh->n_descsz)) + break; + + if (nh->n_type == NT_GNU_BUILD_ID + && nh->n_descsz > 0 + && nh->n_namesz == sizeof "GNU" + && !memcmp (note_name, "GNU", sizeof "GNU")) + { + build_id->vaddr = note_desc - (const void *) notes + vaddr; + build_id->len = nh->n_descsz; + build_id->memory = malloc (build_id->len); + if (likely (build_id->memory != NULL)) + memcpy (build_id->memory, note_desc, build_id->len); + break; + } + + len += nh->n_descsz; + len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len); + nh = (void *) notes + len; + } + +done: + if (notes != data) + free (notes); + finish_portion (dwfl, memory_callback, memory_callback_arg, &data, &data_size); +} + int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, Dwfl_Memory_Callback *memory_callback, @@ -454,89 +547,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, build_id.len = 0; build_id.vaddr =0; - /* Consider a PT_NOTE we've found in the image. */ - inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz, - GElf_Xword align) - { - /* If we have already seen a build ID, we don't care any more. */ - if (build_id.memory != NULL || filesz == 0) - return; - - void *data; - size_t data_size; - if (read_portion (dwfl, memory_callback, memory_callback_arg, - &data, &data_size, vaddr, filesz, - buffer, buffer_available, start, segment)) - return; - - /* data_size will be zero if we got everything from the initial - buffer, otherwise it will be the size of the new buffer that - could be read. */ - if (data_size != 0) - filesz = data_size; - - assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); - - void *notes; - if (ei_data == MY_ELFDATA) - notes = data; - else - { - notes = malloc (filesz); - if (unlikely (notes == NULL)) - return; - xlatefrom.d_type = xlateto.d_type = (align == 8 - ? ELF_T_NHDR8 : ELF_T_NHDR); - xlatefrom.d_buf = (void *) data; - xlatefrom.d_size = filesz; - xlateto.d_buf = notes; - xlateto.d_size = filesz; - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - goto done; - } - - const GElf_Nhdr *nh = notes; - size_t len = 0; - while (filesz > len + sizeof (*nh)) - { - const void *note_name; - const void *note_desc; - - len += sizeof (*nh); - note_name = notes + len; - - len += nh->n_namesz; - len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len); - note_desc = notes + len; - - if (unlikely (filesz < len + nh->n_descsz)) - break; - - if (nh->n_type == NT_GNU_BUILD_ID - && nh->n_descsz > 0 - && nh->n_namesz == sizeof "GNU" - && !memcmp (note_name, "GNU", sizeof "GNU")) - { - build_id.vaddr = note_desc - (const void *) notes + vaddr; - build_id.len = nh->n_descsz; - build_id.memory = malloc (build_id.len); - if (likely (build_id.memory != NULL)) - memcpy (build_id.memory, note_desc, build_id.len); - break; - } - - len += nh->n_descsz; - len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len); - nh = (void *) notes + len; - } - - done: - if (notes != data) - free (notes); - finish_portion (dwfl, memory_callback, memory_callback_arg, &data, &data_size); - } - /* Consider each of the program headers we've read from the image. */ inline void consider_phdr (GElf_Word type, GElf_Addr vaddr, GElf_Xword memsz, @@ -551,9 +561,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, break; case PT_NOTE: - /* We calculate from the p_offset of the note segment, - because we don't yet know the bias for its p_vaddr. */ - consider_notes (start + offset, filesz, align); + /* We calculate from the p_offset of the note segment, + because we don't yet know the bias for its p_vaddr. */ + consider_notes (dwfl, memory_callback, memory_callback_arg, + start + offset, filesz, align, + buffer, buffer_available, start, segment, + ei_data, &build_id, + &xlatefrom, &xlateto, + ehdr.e32.e_ident[EI_DATA]); break; case PT_LOAD: -- 2.26.2