DWARF_GET_RANGES(3)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1, nixpkgs unstable

πŸ’… DWARF_GET_RANGES(3) πŸ’…

okay bestie, welcome to the Library Functions Manual corner of the group chat. today’s main character is dwarf_get_ranges, and we’re getting into non-contiguous address ranges. stay with me, it’s gonna slay.


✨ NAME ✨

dwarf_get_ranges β€” retrieve non-contiguous address ranges


πŸ“š LIBRARY πŸ“š

DWARF Access Library (libdwarf, -ldwarf)


πŸ¦‹ SYNOPSIS πŸ¦‹

       #include <libdwarf.h>

       int
       dwarf_get_ranges(Dwarf_Debug dbg, Dwarf_Off offset,
           Dwarf_Ranges **ranges, Dwarf_Signed *cnt, Dwarf_Unsigned *byte_cnt,
           Dwarf_Error *err);

       int
       dwarf_get_ranges_a(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die die,
           Dwarf_Ranges **ranges, Dwarf_Signed *cnt, Dwarf_Unsigned *byte_cnt,
           Dwarf_Error *err);

πŸ’– DESCRIPTION πŸ’–

okay so dwarf_get_ranges() pulls the info about the non-contiguous address ranges attached to a DWARF debugging information entry. the address-range info comes back as an array of descriptors of type Dwarf_Ranges, and each Dwarf_Ranges descriptor describes one address range entry. iconic, honestly.

Here’s the argument tea, one by one:

  • dbg β€” should reference a DWARF debug context allocated using dwarf_init(3). no random dbg, got it?
  • offset β€” an offset, relative to the .debug_ranges section, to the start of the desired list of address ranges. the offset of an address ranges list is indicated by the DW_AT_ranges attribute of a debugging information entry. follow the little breadcrumb, bestie.
  • die β€” function dwarf_get_ranges_a() only. in this implementation it is ignored; see the section β€œCompatibility Notes” below. yes, ignored. we’ll circle back.
  • ranges β€” should point to a location that will be set to a pointer to an array of Dwarf_Ranges descriptors. so it’s like, pointer to a pointer situation, but make it DWARF.
  • cnt β€” should point to a location that will be set to the number of entries returned. if argument byte_cnt is not NULL, it will be set to the number of bytes occupied by the returned entries in the .debug_ranges section. numbers are coming back, periodt.
  • err β€” if argument err is not NULL, it will be used to store error information in case of an error. error gossip gets stored there.

Dwarf_Ranges descriptors are defined in the header file <libdwarf.h>, and consists of the following fields:

  • dwr_addr1 β€” the first address offset, whose meaning depends on the type of the entry.
  • dwr_addr2 β€” the second address offset, whose meaning depends on the type of the entry.
  • dwr_type β€” the type of this address range entry:
    • DW_RANGES_ENTRY β€” a range list entry. for this type of entry, the fields dwr_addr1 and dwr_addr2 hold the beginning and ending offsets of the address range, respectively. beginning and ending, cute little range sandwich.
    • DW_RANGES_ADDRESS_SELECTION β€” a base address selection entry. for this type of entry, the field dwr_addr1 is the value of the largest representable address offset, and dwr_addr2 is a base address for the beginning and ending address offsets of subsequent address range entries in the list. big address energy.
    • DW_RANGES_END β€” an end of list mark. both dwr_addr1 and dwr_addr2 are set to 0. the end, literally.

🧠 Memory Management 🧠

bestie, listen: the memory area used for the array of Dwarf_Ranges descriptors returned in argument ranges is owned by the DWARF Access Library (libdwarf, -ldwarf). the application should not attempt to directly free this pointer. do not just free() it, okay? that’s not the move.

portable code should instead use dwarf_ranges_dealloc() to indicate that the memory may be freed. that’s the polite, portable way to do it.


🌈 RETURN VALUES 🌈

these functions return DW_DLV_OK when they succeed. yay

they return DW_DLV_NO_ENTRY if there is no address range list at the specified offset offset. nothing there, no entries, moving on

in case of an error, they return DW_DLV_ERROR and set the argument err. error era


πŸ“ EXAMPLES πŸ“

to retrieve the address range list associated with a debugging information entry, use:

             Dwarf_Debug dbg;
             Dwarf_Die die;
             Dwarf_Error de;
             Dwarf_Addr base;
             Dwarf_Attribute *attr_list;
             Dwarf_Ranges *ranges;
             Dwarf_Signed cnt;
             Dwarf_Unsigned off, attr_count, bytecnt;
             int i, j;

             if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
                 DW_DLV_OK)
                     errx(EXIT_FAILURE, "dwarf_attrlist failed: %s",
                         dwarf_errmsg(de));

             for (i = 0; (Dwarf_Unsigned) i < attr_count; i++) {
                     if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
                             warnx("dwarf_whatattr failed: %s",
                                 dwarf_errmsg(de));
                             continue;
                     }
                     if (attr != DW_AT_ranges)
                             continue;
                     if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) {
                             warnx("dwarf_formudata failed: %s",
                                 dwarf_errmsg(de));
                             continue;
                     }
                     if (dwarf_get_ranges(dbg, (Dwarf_Off) off, &ranges, &cnt,
                         &bytecnt, &de) != DW_DLV_OK)
                             continue;
                     for (j = 0; j < cnt; j++) {
                             if (ranges[j].dwr_type == DW_RANGES_END)
                                     break;
                             else if (ranges[j].dwr_type ==
                                 DW_RANGES_ADDRESS_SELECTION)
                                     base = ranges[j].dwr_addr2;
                             else {
                                     /*
                                      * DW_RANGES_ENTRY entry.
                                      * .. Use dwr_addr1 and dwr_addr2 ..
                                      */
                             }
                     }
             }

πŸ’… COMPATIBILITY πŸ’…

function dwarf_get_ranges_a() is identical to dwarf_get_ranges(), except that it requires one additional argument die denoting the debugging information entry associated with the address range list.

in this implementation of the DWARF Access Library (libdwarf, -ldwarf), the argument die is ignored, and function dwarf_get_ranges_a() is only provided for compatibility with other implementations of the DWARF(3) API. so it’s there for the other girls, but this implementation is not using it.


πŸ’€ ERRORS πŸ’€

these functions can fail with:

  • [DW_DLE_ARGUMENT] β€” one of the arguments dbg, ranges or cnt was NULL. null moment, not cute
  • [DW_DLE_NO_ENTRY] β€” there is no address range list at the specified offset offset. empty list energy

πŸ”₯ SEE ALSO πŸ”₯

dwarf(3), dwarf_ranges_dealloc(3)


and that’s the whole DWARF ranges situation, bestie ✨ source/version: Debian Β· date: November 9, 2011 Β· mwah πŸ’‹

πŸ“¦ where this page comes from