On 3/24/24 14:08, Mark Wielaard wrote:
Hi Martin,

On Sun, Mar 24, 2024 at 11:11:21AM -0300, Martin Rodriguez Reboredo wrote:
[...]
So this patch is kinda pointless, but at least I've managed to learn
what I was missing. Anyways, thanks for the heads-up. :)

I don't think it was pointless. Clearly our documentation is not very
good (and given eu-readelf and eu-nm do cheat, maybe our interface/api
isn't really good either).

At least to get the gist of it the header comments were good enough, it
was this particular case that I misunderstood. I could do what I wanted
with the API, so no problem with that.

Maybe you could post your code for that ./report program and what you
had to do to get it to print the correct address/symbols. Then we at
least have some documentation for others which hit the same issue.

    #ifdef USE_DEMANGLE
    #include <cxxabi.h>
    #endif
    #include <elfutils/libdwfl.h>
    #include <dwarf.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>

    static const char *symname(const char *name)
    {
    #ifdef USE_DEMANGLE
      // Require GNU v3 ABI by the "_Z" prefix.
      if (name[0] == '_' && name[1] == 'Z') {
        int status = -1;
        char *dsymname = __cxa_demangle(name, demangle_buffer,
                &demangle_buffer_len, &status);
        if (status == 0)
          name = demangle_buffer = dsymname;
      }
    #endif
      return name;
    }

    static int get_addr_width(Dwfl_Module *mod)
    {
      // Try to find the address width if possible.
      static int width = 0;
      if (width == 0 && mod != NULL) {
        Dwarf_Addr bias;
        Elf *elf = dwfl_module_getelf(mod, &bias);
        if (elf != NULL) {
          GElf_Ehdr ehdr_mem;
          GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_mem);
          if (ehdr != NULL)
            width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ?
                8 :
                16;
        }
      }
      if (width == 0)
        width = 16;

      return width;
    }

    int main(int argc, const char **argv)
    {
      if (argc != 3)
        return 1;

      Dwfl *dwfl = dwfl_begin(&offline_callbacks);
      if (!dwfl)
        return 1;
      //dwfl->offline_next_address = 0; // What I thought it was needed

      if (!dwfl_report_offline(dwfl, "", argv[1], -1)) {
        dwfl_end(dwfl);
        return 1;
      }
      if (dwfl_report_end(dwfl, NULL, NULL)) {
        dwfl_end(dwfl);
        return 1;
      }

      char *endp = NULL;
      GElf_Addr addr = strtoumax(argv[2], &endp, 16), bias;

      Dwfl_Module *mod = dwfl_addrmodule(dwfl, addr);

      int width = get_addr_width(mod);
      printf("0x%.*" PRIx64 "%s", width, addr, "\n");

      dwfl_module_getdwarf(mod, &bias); // This line did the trick!

      const char *name = dwfl_module_addrname(mod, addr + bias);
      name = name != NULL ? symname(name) : "??";
      printf("%s%c", name, '\n');

      GElf_Sym s;
      GElf_Off off = 0;
      name = dwfl_module_addrinfo(mod, addr + bias, &off, &s, NULL, NULL, NULL);

      Dwfl_Line *line = dwfl_module_getsrc(mod, addr + bias);
      if (!line)
        line = dwfl_getsrc(dwfl, addr + bias);
      if (line) {
        int nline, column;
        const char *filename =
          dwfl_lineinfo(line, &addr, &nline, &column, NULL, NULL);
        printf("%s:%i,%i\n", filename, nline, column);
      } else {
        printf("??:0\n");
      }

      dwfl_end(dwfl);

      return 0;
    }

Thanks,

Mark

Reply via email to