1a85fe12eSEd Maste /*- 2a85fe12eSEd Maste * Copyright (c) 2009 Kai Wang 3a85fe12eSEd Maste * All rights reserved. 4a85fe12eSEd Maste * 5a85fe12eSEd Maste * Redistribution and use in source and binary forms, with or without 6a85fe12eSEd Maste * modification, are permitted provided that the following conditions 7a85fe12eSEd Maste * are met: 8a85fe12eSEd Maste * 1. Redistributions of source code must retain the above copyright 9a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer. 10a85fe12eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright 11a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer in the 12a85fe12eSEd Maste * documentation and/or other materials provided with the distribution. 13a85fe12eSEd Maste * 14a85fe12eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15a85fe12eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16a85fe12eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17a85fe12eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18a85fe12eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19a85fe12eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20a85fe12eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21a85fe12eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22a85fe12eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23a85fe12eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24a85fe12eSEd Maste * SUCH DAMAGE. 25a85fe12eSEd Maste */ 26a85fe12eSEd Maste 27a85fe12eSEd Maste #include <sys/param.h> 28a85fe12eSEd Maste #include <dwarf.h> 29a85fe12eSEd Maste #include <err.h> 30a85fe12eSEd Maste #include <fcntl.h> 31a85fe12eSEd Maste #include <gelf.h> 32a85fe12eSEd Maste #include <getopt.h> 33a85fe12eSEd Maste #include <libdwarf.h> 34a85fe12eSEd Maste #include <libelftc.h> 35a85fe12eSEd Maste #include <libgen.h> 36a85fe12eSEd Maste #include <stdio.h> 37a85fe12eSEd Maste #include <stdlib.h> 38a85fe12eSEd Maste #include <string.h> 39a85fe12eSEd Maste 40a85fe12eSEd Maste #include "_elftc.h" 41a85fe12eSEd Maste 42656f49f8SEd Maste ELFTC_VCSID("$Id: addr2line.c 3249 2015-10-04 08:11:30Z kaiwang27 $"); 43a85fe12eSEd Maste 44a85fe12eSEd Maste static struct option longopts[] = { 45a85fe12eSEd Maste {"target" , required_argument, NULL, 'b'}, 46a85fe12eSEd Maste {"demangle", no_argument, NULL, 'C'}, 47a85fe12eSEd Maste {"exe", required_argument, NULL, 'e'}, 48a85fe12eSEd Maste {"functions", no_argument, NULL, 'f'}, 49a85fe12eSEd Maste {"section", required_argument, NULL, 'j'}, 50a85fe12eSEd Maste {"basename", no_argument, NULL, 's'}, 51a85fe12eSEd Maste {"help", no_argument, NULL, 'H'}, 52a85fe12eSEd Maste {"version", no_argument, NULL, 'V'}, 53a85fe12eSEd Maste {NULL, 0, NULL, 0} 54a85fe12eSEd Maste }; 55a85fe12eSEd Maste static int demangle, func, base; 56a85fe12eSEd Maste static char unknown[] = { '?', '?', '\0' }; 57a85fe12eSEd Maste static Dwarf_Addr section_base; 58a85fe12eSEd Maste 59a85fe12eSEd Maste #define USAGE_MESSAGE "\ 60a85fe12eSEd Maste Usage: %s [options] hexaddress...\n\ 61a85fe12eSEd Maste Map program addresses to source file names and line numbers.\n\n\ 62a85fe12eSEd Maste Options:\n\ 63a85fe12eSEd Maste -b TGT | --target=TGT (Accepted but ignored).\n\ 64656f49f8SEd Maste -e EXE | --exe=EXE Use program \"EXE\" to translate addresses.\n\ 65a85fe12eSEd Maste -f | --functions Display function names.\n\ 66a85fe12eSEd Maste -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ 67a85fe12eSEd Maste -s | --basename Only show the base name for each file name.\n\ 68a85fe12eSEd Maste -C | --demangle Demangle C++ names.\n\ 69a85fe12eSEd Maste -H | --help Print a help message.\n\ 70a85fe12eSEd Maste -V | --version Print a version identifier and exit.\n" 71a85fe12eSEd Maste 72a85fe12eSEd Maste static void 73a85fe12eSEd Maste usage(void) 74a85fe12eSEd Maste { 75a85fe12eSEd Maste (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 76a85fe12eSEd Maste exit(1); 77a85fe12eSEd Maste } 78a85fe12eSEd Maste 79a85fe12eSEd Maste static void 80a85fe12eSEd Maste version(void) 81a85fe12eSEd Maste { 82a85fe12eSEd Maste 83a85fe12eSEd Maste fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 84a85fe12eSEd Maste exit(0); 85a85fe12eSEd Maste } 86a85fe12eSEd Maste 87b00fe64fSEd Maste /* 88b00fe64fSEd Maste * Handle DWARF 4 'offset from' DW_AT_high_pc. Although we don't 89b00fe64fSEd Maste * fully support DWARF 4, some compilers (like FreeBSD Clang 3.5.1) 90b00fe64fSEd Maste * generate DW_AT_high_pc as an offset from DW_AT_low_pc. 91b00fe64fSEd Maste * 92b00fe64fSEd Maste * "If the value of the DW_AT_high_pc is of class address, it is the 93b00fe64fSEd Maste * relocated address of the first location past the last instruction 94b00fe64fSEd Maste * associated with the entity; if it is of class constant, the value 95b00fe64fSEd Maste * is an unsigned integer offset which when added to the low PC gives 96b00fe64fSEd Maste * the address of the first location past the last instruction 97b00fe64fSEd Maste * associated with the entity." 98b00fe64fSEd Maste * 99b00fe64fSEd Maste * DWARF4 spec, section 2.17.2. 100b00fe64fSEd Maste */ 101b00fe64fSEd Maste static int 102b00fe64fSEd Maste handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc) 103b00fe64fSEd Maste { 104b00fe64fSEd Maste Dwarf_Error de; 105b00fe64fSEd Maste Dwarf_Half form; 106b00fe64fSEd Maste Dwarf_Attribute at; 107b00fe64fSEd Maste int ret; 108b00fe64fSEd Maste 109b00fe64fSEd Maste ret = dwarf_attr(die, DW_AT_high_pc, &at, &de); 110b00fe64fSEd Maste if (ret == DW_DLV_ERROR) { 111b00fe64fSEd Maste warnx("dwarf_attr failed: %s", dwarf_errmsg(de)); 112b00fe64fSEd Maste return (ret); 113b00fe64fSEd Maste } 114b00fe64fSEd Maste ret = dwarf_whatform(at, &form, &de); 115b00fe64fSEd Maste if (ret == DW_DLV_ERROR) { 116b00fe64fSEd Maste warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); 117b00fe64fSEd Maste return (ret); 118b00fe64fSEd Maste } 119b00fe64fSEd Maste if (dwarf_get_form_class(2, 0, 0, form) == DW_FORM_CLASS_CONSTANT) 120b00fe64fSEd Maste *hipc += lopc; 121b00fe64fSEd Maste 122b00fe64fSEd Maste return (DW_DLV_OK); 123b00fe64fSEd Maste } 124b00fe64fSEd Maste 125a85fe12eSEd Maste static void 126656f49f8SEd Maste search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func) 127a85fe12eSEd Maste { 128a85fe12eSEd Maste Dwarf_Die ret_die, spec_die; 129a85fe12eSEd Maste Dwarf_Error de; 130a85fe12eSEd Maste Dwarf_Half tag; 131a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc; 132a85fe12eSEd Maste Dwarf_Off ref; 133a85fe12eSEd Maste Dwarf_Attribute sub_at, spec_at; 134a85fe12eSEd Maste char *func0; 135656f49f8SEd Maste const char *func1; 136a85fe12eSEd Maste int ret; 137a85fe12eSEd Maste 138a85fe12eSEd Maste if (*rlt_func != NULL) 139656f49f8SEd Maste goto done; 140a85fe12eSEd Maste 141a85fe12eSEd Maste if (dwarf_tag(die, &tag, &de)) { 142a85fe12eSEd Maste warnx("dwarf_tag: %s", dwarf_errmsg(de)); 143a85fe12eSEd Maste goto cont_search; 144a85fe12eSEd Maste } 145a85fe12eSEd Maste if (tag == DW_TAG_subprogram) { 146a85fe12eSEd Maste if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || 147a85fe12eSEd Maste dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) 148a85fe12eSEd Maste goto cont_search; 149b00fe64fSEd Maste if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) 150b00fe64fSEd Maste goto cont_search; 151a85fe12eSEd Maste if (addr < lopc || addr >= hipc) 152a85fe12eSEd Maste goto cont_search; 153a85fe12eSEd Maste 154a85fe12eSEd Maste /* Found it! */ 155a85fe12eSEd Maste 156656f49f8SEd Maste if ((*rlt_func = strdup(unknown)) == NULL) 157656f49f8SEd Maste err(EXIT_FAILURE, "strdup"); 158a85fe12eSEd Maste ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); 159a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 160656f49f8SEd Maste goto done; 161a85fe12eSEd Maste if (ret == DW_DLV_OK) { 162656f49f8SEd Maste if (dwarf_formstring(sub_at, &func0, &de) == 163656f49f8SEd Maste DW_DLV_OK) { 164656f49f8SEd Maste free(*rlt_func); 165656f49f8SEd Maste if ((*rlt_func = strdup(func0)) == NULL) 166656f49f8SEd Maste err(EXIT_FAILURE, "strdup"); 167656f49f8SEd Maste } 168656f49f8SEd Maste goto done; 169a85fe12eSEd Maste } 170a85fe12eSEd Maste 171a85fe12eSEd Maste /* 172a85fe12eSEd Maste * If DW_AT_name is not present, but DW_AT_specification is 173a85fe12eSEd Maste * present, then probably the actual name is in the DIE 174a85fe12eSEd Maste * referenced by DW_AT_specification. 175a85fe12eSEd Maste */ 176a85fe12eSEd Maste if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) 177656f49f8SEd Maste goto done; 178a85fe12eSEd Maste if (dwarf_global_formref(spec_at, &ref, &de)) 179656f49f8SEd Maste goto done; 180a85fe12eSEd Maste if (dwarf_offdie(dbg, ref, &spec_die, &de)) 181656f49f8SEd Maste goto done; 182656f49f8SEd Maste if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) == 183656f49f8SEd Maste DW_DLV_OK) { 184656f49f8SEd Maste free(*rlt_func); 185656f49f8SEd Maste if ((*rlt_func = strdup(func1)) == NULL) 186656f49f8SEd Maste err(EXIT_FAILURE, "strdup"); 187656f49f8SEd Maste } 188a85fe12eSEd Maste 189656f49f8SEd Maste goto done; 190a85fe12eSEd Maste } 191a85fe12eSEd Maste 192a85fe12eSEd Maste cont_search: 193a85fe12eSEd Maste 194a85fe12eSEd Maste /* Search children. */ 195a85fe12eSEd Maste ret = dwarf_child(die, &ret_die, &de); 196a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 197a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); 198a85fe12eSEd Maste else if (ret == DW_DLV_OK) 199a85fe12eSEd Maste search_func(dbg, ret_die, addr, rlt_func); 200a85fe12eSEd Maste 201a85fe12eSEd Maste /* Search sibling. */ 202a85fe12eSEd Maste ret = dwarf_siblingof(dbg, die, &ret_die, &de); 203a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 204a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); 205a85fe12eSEd Maste else if (ret == DW_DLV_OK) 206a85fe12eSEd Maste search_func(dbg, ret_die, addr, rlt_func); 207656f49f8SEd Maste 208656f49f8SEd Maste done: 209656f49f8SEd Maste dwarf_dealloc(dbg, die, DW_DLA_DIE); 210a85fe12eSEd Maste } 211a85fe12eSEd Maste 212a85fe12eSEd Maste static void 213a85fe12eSEd Maste translate(Dwarf_Debug dbg, const char* addrstr) 214a85fe12eSEd Maste { 215656f49f8SEd Maste Dwarf_Die die, ret_die; 216a85fe12eSEd Maste Dwarf_Line *lbuf; 217a85fe12eSEd Maste Dwarf_Error de; 218a85fe12eSEd Maste Dwarf_Half tag; 219a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; 220a85fe12eSEd Maste Dwarf_Signed lcount; 221a85fe12eSEd Maste Dwarf_Addr lineaddr, plineaddr; 222656f49f8SEd Maste char *funcname; 223a85fe12eSEd Maste char *file, *file0, *pfile; 224a85fe12eSEd Maste char demangled[1024]; 225a85fe12eSEd Maste int i, ret; 226a85fe12eSEd Maste 227a85fe12eSEd Maste addr = strtoull(addrstr, NULL, 16); 228a85fe12eSEd Maste addr += section_base; 229a85fe12eSEd Maste lineno = 0; 230a85fe12eSEd Maste file = unknown; 231*7a2e729bSEd Maste die = NULL; 232656f49f8SEd Maste lbuf = NULL; 233656f49f8SEd Maste lcount = 0; 234a85fe12eSEd Maste 235a85fe12eSEd Maste while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 236a85fe12eSEd Maste &de)) == DW_DLV_OK) { 237a85fe12eSEd Maste die = NULL; 238656f49f8SEd Maste while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) { 239656f49f8SEd Maste if (die != NULL) 240656f49f8SEd Maste dwarf_dealloc(dbg, die, DW_DLA_DIE); 241656f49f8SEd Maste die = ret_die; 242a85fe12eSEd Maste if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { 243a85fe12eSEd Maste warnx("dwarf_tag failed: %s", 244a85fe12eSEd Maste dwarf_errmsg(de)); 245656f49f8SEd Maste goto next_cu; 246a85fe12eSEd Maste } 247656f49f8SEd Maste 248a85fe12eSEd Maste /* XXX: What about DW_TAG_partial_unit? */ 249a85fe12eSEd Maste if (tag == DW_TAG_compile_unit) 250a85fe12eSEd Maste break; 251a85fe12eSEd Maste } 252656f49f8SEd Maste if (ret_die == NULL) { 253a85fe12eSEd Maste warnx("could not find DW_TAG_compile_unit die"); 254656f49f8SEd Maste goto next_cu; 255a85fe12eSEd Maste } 256a85fe12eSEd Maste if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && 257a85fe12eSEd Maste !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { 258a85fe12eSEd Maste /* 259a85fe12eSEd Maste * Check if the address falls into the PC range of 260a85fe12eSEd Maste * this CU. 261a85fe12eSEd Maste */ 262b00fe64fSEd Maste if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) 263656f49f8SEd Maste goto next_cu; 264a85fe12eSEd Maste if (addr < lopc || addr >= hipc) 265656f49f8SEd Maste goto next_cu; 266a85fe12eSEd Maste } 267a85fe12eSEd Maste 268c9dbb1ccSEd Maste switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { 269c9dbb1ccSEd Maste case DW_DLV_OK: 270c9dbb1ccSEd Maste break; 271c9dbb1ccSEd Maste case DW_DLV_NO_ENTRY: 272656f49f8SEd Maste /* If a CU lacks debug info, just skip it. */ 273656f49f8SEd Maste goto next_cu; 274c9dbb1ccSEd Maste default: 275a85fe12eSEd Maste warnx("dwarf_srclines: %s", dwarf_errmsg(de)); 276a85fe12eSEd Maste goto out; 277a85fe12eSEd Maste } 278a85fe12eSEd Maste 279a85fe12eSEd Maste plineaddr = ~0ULL; 280a85fe12eSEd Maste plineno = 0; 281a85fe12eSEd Maste pfile = unknown; 282a85fe12eSEd Maste for (i = 0; i < lcount; i++) { 283a85fe12eSEd Maste if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { 284a85fe12eSEd Maste warnx("dwarf_lineaddr: %s", 285a85fe12eSEd Maste dwarf_errmsg(de)); 286a85fe12eSEd Maste goto out; 287a85fe12eSEd Maste } 288a85fe12eSEd Maste if (dwarf_lineno(lbuf[i], &lineno, &de)) { 289a85fe12eSEd Maste warnx("dwarf_lineno: %s", 290a85fe12eSEd Maste dwarf_errmsg(de)); 291a85fe12eSEd Maste goto out; 292a85fe12eSEd Maste } 293a85fe12eSEd Maste if (dwarf_linesrc(lbuf[i], &file0, &de)) { 294a85fe12eSEd Maste warnx("dwarf_linesrc: %s", 295a85fe12eSEd Maste dwarf_errmsg(de)); 296a85fe12eSEd Maste } else 297a85fe12eSEd Maste file = file0; 298a85fe12eSEd Maste if (addr == lineaddr) 299a85fe12eSEd Maste goto out; 300a85fe12eSEd Maste else if (addr < lineaddr && addr > plineaddr) { 301a85fe12eSEd Maste lineno = plineno; 302a85fe12eSEd Maste file = pfile; 303a85fe12eSEd Maste goto out; 304a85fe12eSEd Maste } 305a85fe12eSEd Maste plineaddr = lineaddr; 306a85fe12eSEd Maste plineno = lineno; 307a85fe12eSEd Maste pfile = file; 308a85fe12eSEd Maste } 309656f49f8SEd Maste next_cu: 310656f49f8SEd Maste if (die != NULL) { 311656f49f8SEd Maste dwarf_dealloc(dbg, die, DW_DLA_DIE); 312656f49f8SEd Maste die = NULL; 313656f49f8SEd Maste } 314a85fe12eSEd Maste } 315a85fe12eSEd Maste 316a85fe12eSEd Maste out: 317a85fe12eSEd Maste funcname = NULL; 318656f49f8SEd Maste if (ret == DW_DLV_OK && func) { 319a85fe12eSEd Maste search_func(dbg, die, addr, &funcname); 320656f49f8SEd Maste die = NULL; 321656f49f8SEd Maste } 322a85fe12eSEd Maste 323a85fe12eSEd Maste if (func) { 324a85fe12eSEd Maste if (funcname == NULL) 325656f49f8SEd Maste if ((funcname = strdup(unknown)) == NULL) 326656f49f8SEd Maste err(EXIT_FAILURE, "strdup"); 327a85fe12eSEd Maste if (demangle && 328a85fe12eSEd Maste !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) 329a85fe12eSEd Maste printf("%s\n", demangled); 330a85fe12eSEd Maste else 331a85fe12eSEd Maste printf("%s\n", funcname); 332656f49f8SEd Maste free(funcname); 333a85fe12eSEd Maste } 334a85fe12eSEd Maste 335a85fe12eSEd Maste (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); 336a85fe12eSEd Maste 337656f49f8SEd Maste if (die != NULL) 338656f49f8SEd Maste dwarf_dealloc(dbg, die, DW_DLA_DIE); 339656f49f8SEd Maste 340a85fe12eSEd Maste /* 341a85fe12eSEd Maste * Reset internal CU pointer, so we will start from the first CU 342a85fe12eSEd Maste * next round. 343a85fe12eSEd Maste */ 344a85fe12eSEd Maste while (ret != DW_DLV_NO_ENTRY) { 345a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 346a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", 347a85fe12eSEd Maste dwarf_errmsg(de)); 348a85fe12eSEd Maste ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 349a85fe12eSEd Maste &de); 350a85fe12eSEd Maste } 351a85fe12eSEd Maste } 352a85fe12eSEd Maste 353a85fe12eSEd Maste static void 354a85fe12eSEd Maste find_section_base(const char *exe, Elf *e, const char *section) 355a85fe12eSEd Maste { 356a85fe12eSEd Maste Dwarf_Addr off; 357a85fe12eSEd Maste Elf_Scn *scn; 358a85fe12eSEd Maste GElf_Ehdr eh; 359a85fe12eSEd Maste GElf_Shdr sh; 360a85fe12eSEd Maste size_t shstrndx; 361a85fe12eSEd Maste int elferr; 362a85fe12eSEd Maste const char *name; 363a85fe12eSEd Maste 364a85fe12eSEd Maste if (gelf_getehdr(e, &eh) != &eh) { 365a85fe12eSEd Maste warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 366a85fe12eSEd Maste return; 367a85fe12eSEd Maste } 368a85fe12eSEd Maste 369a85fe12eSEd Maste if (!elf_getshstrndx(e, &shstrndx)) { 370a85fe12eSEd Maste warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 371a85fe12eSEd Maste return; 372a85fe12eSEd Maste } 373a85fe12eSEd Maste 374a85fe12eSEd Maste (void) elf_errno(); 375a85fe12eSEd Maste off = 0; 376a85fe12eSEd Maste scn = NULL; 377a85fe12eSEd Maste while ((scn = elf_nextscn(e, scn)) != NULL) { 378a85fe12eSEd Maste if (gelf_getshdr(scn, &sh) == NULL) { 379a85fe12eSEd Maste warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 380a85fe12eSEd Maste continue; 381a85fe12eSEd Maste } 382a85fe12eSEd Maste if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) 383a85fe12eSEd Maste goto next; 384a85fe12eSEd Maste if (!strcmp(section, name)) { 385a85fe12eSEd Maste if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { 386a85fe12eSEd Maste /* 387a85fe12eSEd Maste * For executables, section base is the virtual 388a85fe12eSEd Maste * address of the specified section. 389a85fe12eSEd Maste */ 390a85fe12eSEd Maste section_base = sh.sh_addr; 391a85fe12eSEd Maste } else if (eh.e_type == ET_REL) { 392a85fe12eSEd Maste /* 393a85fe12eSEd Maste * For relocatables, section base is the 394a85fe12eSEd Maste * relative offset of the specified section 395a85fe12eSEd Maste * to the start of the first section. 396a85fe12eSEd Maste */ 397a85fe12eSEd Maste section_base = off; 398a85fe12eSEd Maste } else 399a85fe12eSEd Maste warnx("unknown e_type %u", eh.e_type); 400a85fe12eSEd Maste return; 401a85fe12eSEd Maste } 402a85fe12eSEd Maste next: 403a85fe12eSEd Maste off += sh.sh_size; 404a85fe12eSEd Maste } 405a85fe12eSEd Maste elferr = elf_errno(); 406a85fe12eSEd Maste if (elferr != 0) 407a85fe12eSEd Maste warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 408a85fe12eSEd Maste 409a85fe12eSEd Maste errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); 410a85fe12eSEd Maste } 411a85fe12eSEd Maste 412a85fe12eSEd Maste int 413a85fe12eSEd Maste main(int argc, char **argv) 414a85fe12eSEd Maste { 415a85fe12eSEd Maste Elf *e; 416a85fe12eSEd Maste Dwarf_Debug dbg; 417a85fe12eSEd Maste Dwarf_Error de; 418a85fe12eSEd Maste const char *exe, *section; 419a85fe12eSEd Maste char line[1024]; 420a85fe12eSEd Maste int fd, i, opt; 421a85fe12eSEd Maste 422a85fe12eSEd Maste exe = NULL; 423a85fe12eSEd Maste section = NULL; 424a85fe12eSEd Maste while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != 425a85fe12eSEd Maste -1) { 426a85fe12eSEd Maste switch (opt) { 427a85fe12eSEd Maste case 'b': 428a85fe12eSEd Maste /* ignored */ 429a85fe12eSEd Maste break; 430a85fe12eSEd Maste case 'C': 431a85fe12eSEd Maste demangle = 1; 432a85fe12eSEd Maste break; 433a85fe12eSEd Maste case 'e': 434a85fe12eSEd Maste exe = optarg; 435a85fe12eSEd Maste break; 436a85fe12eSEd Maste case 'f': 437a85fe12eSEd Maste func = 1; 438a85fe12eSEd Maste break; 439a85fe12eSEd Maste case 'j': 440a85fe12eSEd Maste section = optarg; 441a85fe12eSEd Maste break; 442a85fe12eSEd Maste case 's': 443a85fe12eSEd Maste base = 1; 444a85fe12eSEd Maste break; 445a85fe12eSEd Maste case 'H': 446a85fe12eSEd Maste usage(); 447a85fe12eSEd Maste case 'V': 448a85fe12eSEd Maste version(); 449a85fe12eSEd Maste default: 450a85fe12eSEd Maste usage(); 451a85fe12eSEd Maste } 452a85fe12eSEd Maste } 453a85fe12eSEd Maste 454a85fe12eSEd Maste argv += optind; 455a85fe12eSEd Maste argc -= optind; 456a85fe12eSEd Maste 457a85fe12eSEd Maste if (exe == NULL) 458a85fe12eSEd Maste exe = "a.out"; 459a85fe12eSEd Maste 460a85fe12eSEd Maste if ((fd = open(exe, O_RDONLY)) < 0) 461a85fe12eSEd Maste err(EXIT_FAILURE, "%s", exe); 462a85fe12eSEd Maste 463a85fe12eSEd Maste if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) 464a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); 465a85fe12eSEd Maste 466a85fe12eSEd Maste if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) 467a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); 468a85fe12eSEd Maste 469a85fe12eSEd Maste if (section) 470a85fe12eSEd Maste find_section_base(exe, e, section); 471a85fe12eSEd Maste else 472a85fe12eSEd Maste section_base = 0; 473a85fe12eSEd Maste 474a85fe12eSEd Maste if (argc > 0) 475a85fe12eSEd Maste for (i = 0; i < argc; i++) 476a85fe12eSEd Maste translate(dbg, argv[i]); 477a85fe12eSEd Maste else 478a7265433SEd Maste while (fgets(line, sizeof(line), stdin) != NULL) { 479a85fe12eSEd Maste translate(dbg, line); 480a7265433SEd Maste fflush(stdout); 481a7265433SEd Maste } 482a85fe12eSEd Maste 483a85fe12eSEd Maste dwarf_finish(dbg, &de); 484a85fe12eSEd Maste 485a85fe12eSEd Maste (void) elf_end(e); 486a85fe12eSEd Maste 487a85fe12eSEd Maste exit(0); 488a85fe12eSEd Maste } 489