Summary: | Provide a public debug section relocation function | ||
---|---|---|---|
Product: | elfutils | Reporter: | Mark Wielaard <mark> |
Component: | libdw | Assignee: | Di Chen <dichen> |
Status: | NEW --- | ||
Severity: | normal | CC: | amerey, dichen, elfutils-devel, tuliom |
Priority: | P2 | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Mark Wielaard
2024-03-03 12:19:09 UTC
This is the current "workaround" I use when working with individual ET_REL DWARF files (also works for any other ELF type): static char *debuginfo_path = NULL; static const Dwfl_Callbacks dwfl_callbacks = { .find_elf = dwfl_build_id_find_elf, .find_debuginfo = dwfl_standard_find_debuginfo, .section_address = dwfl_offline_section_address, .debuginfo_path = &debuginfo_path, }; int main (int argc, char **argv) { Dwfl *dwfl = dwfl_begin (&dwfl_callbacks); Dwfl_Module *module = dwfl_report_elf (dwfl, argv[1], argv[1], -1, 0, false); if (module == NULL) printf ("%s\n", dwfl_errmsg (-1)); dwfl_report_end (dwfl, NULL, NULL); Dwarf_Addr bias; Dwarf *dwarf = dwfl_module_getdwarf (module, &bias); if (dwarf == NULL) printf ("%s\n", dwfl_errmsg (-1)); /* ... do something with dwarf ... */ dwfl_end (dwfl); // Also cleans up dwarf. } But this is obviously a little cumbersome if not really using any other libdwfl features. Hey @mjw ``` $ eu-readelf -a qq.o | grep Type Type: REL (Relocatable file) $ eu-readelf -S qq.o | grep REL [ 2] .rela.text RELA 0000000000000000 000004b8 00000048 24 I 19 1 8 [ 6] .rela.debug_info RELA 0000000000000000 00000500 000000f0 24 I 19 5 8 [ 9] .rela.debug_aranges RELA 0000000000000000 000005f0 00000030 24 I 19 8 8 [11] .rela.debug_line RELA 0000000000000000 00000620 00000060 24 I 19 10 8 [18] .rela.eh_frame RELA 0000000000000000 00000680 00000030 24 I 19 17 8 ``` When applying relocation on a relocatable file (the above qq.o) with the new function dwelf_relocation_debug_sections (Elf *elf), it only needs to apply relocation on debug sections (which are [ 6] .rela.debug_info, [ 9] .rela.debug_aranges, [11] .rela.debug_line ), am I right? Yes, just process the .rela.debug_* sections. Note that you don't need to depend on the exact name. You can follow the section header sh_info field, which points to the section (number) to which the relocations apply. If that section starts with .debug you can apply the relocations. Or better use ebl_debugscn_p, which checks against the list in libebl/eblopenbackend.c (default_debugscn_p). See also in strip.c, where it says: /* Make sure that this relocation section points to a section to relocate with contents, that isn't allocated and that is a debug section. */ Or libdwfl/relocate.c (relocate_section). Which contains similar logic. @mjw I have function dwelf_relocation_debug_sections() added in libdwelf.a. ``` $ pwd /home/dichen/elfutils $ eu-readelf -s libdwelf/libdwelf.a | grep dwelf_relocation_debug_sections libdwelf/libdwelf.a(dwelf_relocation_debug_sections.o): 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS dwelf_relocation_debug_sections.c 290: 000000000000077c 3783 FUNC GLOBAL DEFAULT 126 dwelf_relocation_debug_sections ``` And I can call the new function in a test program: ``` #include <fcntl.h> #include <gelf.h> #include <libelf.h> #include <stdio.h> #include <unistd.h> #include "libdwelf.h" int main(int argc, char **argv) { const char *fname = argv[1]; elf_version(EV_CURRENT); int fd = open(argv[1], O_RDWR); Elf *elf; elf = elf_begin(fd, ELF_C_RDWR, NULL); dwelf_relocation_debug_sections(elf, fname); elf_update(elf, ELF_C_WRITE); return 0; } // $ gcc reloc.c -l elf -l dwelf -l dw -l ebl -l ebl_backends -l cpu -L ../libcpu -L ../libebl -L ../backends -L ../libdwelf -I ../libdwelf -I ../libdw -g -o reloc ``` Then, I am thinking of making strip.c use this dwelf_relocation_debug_sections() so that I can reduce some code redundancy. ``` diff --git a/src/Makefile.am b/src/Makefile.am index 1d592d4d..746c8817 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,8 @@ if BUILD_STATIC libasm = ../libasm/libasm.a libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) -ldl -lpthread libelf = ../libelf/libelf.a -lz $(zstd_LIBS) +libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a +libdwelf = ../libdwelf/libdwelf.a if LIBDEBUGINFOD libdebuginfod = ../debuginfod/libdebuginfod.a -lpthread $(libcurl_LIBS) else @@ -60,6 +62,7 @@ endif endif libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a libeu = ../lib/libeu.a +libdwelf = ../libdwelf/libdwelf.a if DEMANGLE demanglelib = -lstdc++ @@ -81,7 +84,7 @@ readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) $(obstack_LIBS) \ $(demanglelib) size_LDADD = $(libelf) $(libeu) $(argp_LDADD) -strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) +strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libdwelf) $(argp_LDADD) elflint_LDADD = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD) findtextrel_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) addr2line_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) $(demanglelib) ``` After the above Makefile.am change, still, elfutils building kept failing due to some undefined reference error. ``` /usr/bin/ld: strip.o: in function `handle_debug_relocs': /home/dichen/elfutils/src/strip.c:576: undefined reference to `dwelf_relocation_debug_sections' /usr/bin/ld: strip.o: in function `handle_elf': /home/dichen/elfutils/src/strip.c:2123: undefined reference to `dwelf_relocation_debug_sections' collect2: error: ld returned 1 exit status ``` I believe I am missing something in the building process(Makefile.am, Makefile.in, etc). But I don't have many clue now, could you please give a look? CC: @amerey (In reply to Di Chen from comment #4) > diff --git a/src/Makefile.am b/src/Makefile.am > index 1d592d4d..746c8817 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -43,6 +43,8 @@ if BUILD_STATIC > libasm = ../libasm/libasm.a > libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) -ldl -lpthread > libelf = ../libelf/libelf.a -lz $(zstd_LIBS) > +libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a > +libdwelf = ../libdwelf/libdwelf.a > if LIBDEBUGINFOD > libdebuginfod = ../debuginfod/libdebuginfod.a -lpthread $(libcurl_LIBS) > else > @@ -60,6 +62,7 @@ endif > endif > libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a > libeu = ../lib/libeu.a > +libdwelf = ../libdwelf/libdwelf.a > > if DEMANGLE > demanglelib = -lstdc++ > @@ -81,7 +84,7 @@ readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) > $(argp_LDADD) > nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) > $(obstack_LIBS) \ > $(demanglelib) > size_LDADD = $(libelf) $(libeu) $(argp_LDADD) > -strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) > +strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libdwelf) > $(argp_LDADD) > elflint_LDADD = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD) > findtextrel_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) > addr2line_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) $(demanglelib) These Makefile changes aren't needed since strip is already built with libdwelf and using libdwelf functions. Reverting these Makefile changes should fix the linker error. @amerey I believe your elfutils was lacking the dwelf_relocation_debug_sections replacement in strip.c while compiling. Could you give a double check for whether the dwelf_relocation_debug_sections is introduced in strip binary? $ eu-readelf -s {strip} | grep dwelf_relocation This issue is in code review. https://sourceware.org/pipermail/elfutils-devel/2024q3/007388.html |