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 42b00fe64fSEd Maste ELFTC_VCSID("$Id: addr2line.c 3197 2015-05-12 21:01:31Z emaste $"); 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\ 64a85fe12eSEd Maste -e EXE | --exec=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 126a85fe12eSEd Maste search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, 127a85fe12eSEd Maste const char **rlt_func) 128a85fe12eSEd Maste { 129a85fe12eSEd Maste Dwarf_Die ret_die, spec_die; 130a85fe12eSEd Maste Dwarf_Error de; 131a85fe12eSEd Maste Dwarf_Half tag; 132a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc; 133a85fe12eSEd Maste Dwarf_Off ref; 134a85fe12eSEd Maste Dwarf_Attribute sub_at, spec_at; 135a85fe12eSEd Maste char *func0; 136a85fe12eSEd Maste int ret; 137a85fe12eSEd Maste 138a85fe12eSEd Maste if (*rlt_func != NULL) 139a85fe12eSEd Maste return; 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 156a85fe12eSEd Maste *rlt_func = unknown; 157a85fe12eSEd Maste ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); 158a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 159a85fe12eSEd Maste return; 160a85fe12eSEd Maste if (ret == DW_DLV_OK) { 161a85fe12eSEd Maste if (dwarf_formstring(sub_at, &func0, &de)) 162a85fe12eSEd Maste *rlt_func = unknown; 163a85fe12eSEd Maste else 164a85fe12eSEd Maste *rlt_func = func0; 165a85fe12eSEd Maste return; 166a85fe12eSEd Maste } 167a85fe12eSEd Maste 168a85fe12eSEd Maste /* 169a85fe12eSEd Maste * If DW_AT_name is not present, but DW_AT_specification is 170a85fe12eSEd Maste * present, then probably the actual name is in the DIE 171a85fe12eSEd Maste * referenced by DW_AT_specification. 172a85fe12eSEd Maste */ 173a85fe12eSEd Maste if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) 174a85fe12eSEd Maste return; 175a85fe12eSEd Maste if (dwarf_global_formref(spec_at, &ref, &de)) 176a85fe12eSEd Maste return; 177a85fe12eSEd Maste if (dwarf_offdie(dbg, ref, &spec_die, &de)) 178a85fe12eSEd Maste return; 179a85fe12eSEd Maste if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) 180a85fe12eSEd Maste *rlt_func = unknown; 181a85fe12eSEd Maste 182a85fe12eSEd Maste return; 183a85fe12eSEd Maste } 184a85fe12eSEd Maste 185a85fe12eSEd Maste cont_search: 186a85fe12eSEd Maste 187a85fe12eSEd Maste /* Search children. */ 188a85fe12eSEd Maste ret = dwarf_child(die, &ret_die, &de); 189a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 190a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); 191a85fe12eSEd Maste else if (ret == DW_DLV_OK) 192a85fe12eSEd Maste search_func(dbg, ret_die, addr, rlt_func); 193a85fe12eSEd Maste 194a85fe12eSEd Maste /* Search sibling. */ 195a85fe12eSEd Maste ret = dwarf_siblingof(dbg, die, &ret_die, &de); 196a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 197a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_siblingof: %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 202a85fe12eSEd Maste static void 203a85fe12eSEd Maste translate(Dwarf_Debug dbg, const char* addrstr) 204a85fe12eSEd Maste { 205a85fe12eSEd Maste Dwarf_Die die; 206a85fe12eSEd Maste Dwarf_Line *lbuf; 207a85fe12eSEd Maste Dwarf_Error de; 208a85fe12eSEd Maste Dwarf_Half tag; 209a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; 210a85fe12eSEd Maste Dwarf_Signed lcount; 211a85fe12eSEd Maste Dwarf_Addr lineaddr, plineaddr; 212a85fe12eSEd Maste const char *funcname; 213a85fe12eSEd Maste char *file, *file0, *pfile; 214a85fe12eSEd Maste char demangled[1024]; 215a85fe12eSEd Maste int i, ret; 216a85fe12eSEd Maste 217a85fe12eSEd Maste addr = strtoull(addrstr, NULL, 16); 218a85fe12eSEd Maste addr += section_base; 219a85fe12eSEd Maste lineno = 0; 220a85fe12eSEd Maste file = unknown; 221a85fe12eSEd Maste 222a85fe12eSEd Maste while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 223a85fe12eSEd Maste &de)) == DW_DLV_OK) { 224a85fe12eSEd Maste die = NULL; 225a85fe12eSEd Maste while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { 226a85fe12eSEd Maste if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { 227a85fe12eSEd Maste warnx("dwarf_tag failed: %s", 228a85fe12eSEd Maste dwarf_errmsg(de)); 229a85fe12eSEd Maste goto out; 230a85fe12eSEd Maste } 231a85fe12eSEd Maste /* XXX: What about DW_TAG_partial_unit? */ 232a85fe12eSEd Maste if (tag == DW_TAG_compile_unit) 233a85fe12eSEd Maste break; 234a85fe12eSEd Maste } 235a85fe12eSEd Maste if (die == NULL) { 236a85fe12eSEd Maste warnx("could not find DW_TAG_compile_unit die"); 237a85fe12eSEd Maste goto out; 238a85fe12eSEd Maste } 239a85fe12eSEd Maste if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && 240a85fe12eSEd Maste !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { 241a85fe12eSEd Maste /* 242a85fe12eSEd Maste * Check if the address falls into the PC range of 243a85fe12eSEd Maste * this CU. 244a85fe12eSEd Maste */ 245b00fe64fSEd Maste if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) 246b00fe64fSEd Maste continue; 247a85fe12eSEd Maste if (addr < lopc || addr >= hipc) 248a85fe12eSEd Maste continue; 249a85fe12eSEd Maste } 250a85fe12eSEd Maste 251*c9dbb1ccSEd Maste switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { 252*c9dbb1ccSEd Maste case DW_DLV_OK: 253*c9dbb1ccSEd Maste break; 254*c9dbb1ccSEd Maste case DW_DLV_NO_ENTRY: 255*c9dbb1ccSEd Maste /* If one CU lacks debug info, just skip it. */ 256*c9dbb1ccSEd Maste continue; 257*c9dbb1ccSEd Maste default: 258a85fe12eSEd Maste warnx("dwarf_srclines: %s", dwarf_errmsg(de)); 259a85fe12eSEd Maste goto out; 260a85fe12eSEd Maste } 261a85fe12eSEd Maste 262a85fe12eSEd Maste plineaddr = ~0ULL; 263a85fe12eSEd Maste plineno = 0; 264a85fe12eSEd Maste pfile = unknown; 265a85fe12eSEd Maste for (i = 0; i < lcount; i++) { 266a85fe12eSEd Maste if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { 267a85fe12eSEd Maste warnx("dwarf_lineaddr: %s", 268a85fe12eSEd Maste dwarf_errmsg(de)); 269a85fe12eSEd Maste goto out; 270a85fe12eSEd Maste } 271a85fe12eSEd Maste if (dwarf_lineno(lbuf[i], &lineno, &de)) { 272a85fe12eSEd Maste warnx("dwarf_lineno: %s", 273a85fe12eSEd Maste dwarf_errmsg(de)); 274a85fe12eSEd Maste goto out; 275a85fe12eSEd Maste } 276a85fe12eSEd Maste if (dwarf_linesrc(lbuf[i], &file0, &de)) { 277a85fe12eSEd Maste warnx("dwarf_linesrc: %s", 278a85fe12eSEd Maste dwarf_errmsg(de)); 279a85fe12eSEd Maste } else 280a85fe12eSEd Maste file = file0; 281a85fe12eSEd Maste if (addr == lineaddr) 282a85fe12eSEd Maste goto out; 283a85fe12eSEd Maste else if (addr < lineaddr && addr > plineaddr) { 284a85fe12eSEd Maste lineno = plineno; 285a85fe12eSEd Maste file = pfile; 286a85fe12eSEd Maste goto out; 287a85fe12eSEd Maste } 288a85fe12eSEd Maste plineaddr = lineaddr; 289a85fe12eSEd Maste plineno = lineno; 290a85fe12eSEd Maste pfile = file; 291a85fe12eSEd Maste } 292a85fe12eSEd Maste } 293a85fe12eSEd Maste 294a85fe12eSEd Maste out: 295a85fe12eSEd Maste funcname = NULL; 296a85fe12eSEd Maste if (ret == DW_DLV_OK && func) 297a85fe12eSEd Maste search_func(dbg, die, addr, &funcname); 298a85fe12eSEd Maste 299a85fe12eSEd Maste if (func) { 300a85fe12eSEd Maste if (funcname == NULL) 301a85fe12eSEd Maste funcname = unknown; 302a85fe12eSEd Maste if (demangle && 303a85fe12eSEd Maste !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) 304a85fe12eSEd Maste printf("%s\n", demangled); 305a85fe12eSEd Maste else 306a85fe12eSEd Maste printf("%s\n", funcname); 307a85fe12eSEd Maste } 308a85fe12eSEd Maste 309a85fe12eSEd Maste (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); 310a85fe12eSEd Maste 311a85fe12eSEd Maste /* 312a85fe12eSEd Maste * Reset internal CU pointer, so we will start from the first CU 313a85fe12eSEd Maste * next round. 314a85fe12eSEd Maste */ 315a85fe12eSEd Maste while (ret != DW_DLV_NO_ENTRY) { 316a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 317a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", 318a85fe12eSEd Maste dwarf_errmsg(de)); 319a85fe12eSEd Maste ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 320a85fe12eSEd Maste &de); 321a85fe12eSEd Maste } 322a85fe12eSEd Maste } 323a85fe12eSEd Maste 324a85fe12eSEd Maste static void 325a85fe12eSEd Maste find_section_base(const char *exe, Elf *e, const char *section) 326a85fe12eSEd Maste { 327a85fe12eSEd Maste Dwarf_Addr off; 328a85fe12eSEd Maste Elf_Scn *scn; 329a85fe12eSEd Maste GElf_Ehdr eh; 330a85fe12eSEd Maste GElf_Shdr sh; 331a85fe12eSEd Maste size_t shstrndx; 332a85fe12eSEd Maste int elferr; 333a85fe12eSEd Maste const char *name; 334a85fe12eSEd Maste 335a85fe12eSEd Maste if (gelf_getehdr(e, &eh) != &eh) { 336a85fe12eSEd Maste warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 337a85fe12eSEd Maste return; 338a85fe12eSEd Maste } 339a85fe12eSEd Maste 340a85fe12eSEd Maste if (!elf_getshstrndx(e, &shstrndx)) { 341a85fe12eSEd Maste warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 342a85fe12eSEd Maste return; 343a85fe12eSEd Maste } 344a85fe12eSEd Maste 345a85fe12eSEd Maste (void) elf_errno(); 346a85fe12eSEd Maste off = 0; 347a85fe12eSEd Maste scn = NULL; 348a85fe12eSEd Maste while ((scn = elf_nextscn(e, scn)) != NULL) { 349a85fe12eSEd Maste if (gelf_getshdr(scn, &sh) == NULL) { 350a85fe12eSEd Maste warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 351a85fe12eSEd Maste continue; 352a85fe12eSEd Maste } 353a85fe12eSEd Maste if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) 354a85fe12eSEd Maste goto next; 355a85fe12eSEd Maste if (!strcmp(section, name)) { 356a85fe12eSEd Maste if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { 357a85fe12eSEd Maste /* 358a85fe12eSEd Maste * For executables, section base is the virtual 359a85fe12eSEd Maste * address of the specified section. 360a85fe12eSEd Maste */ 361a85fe12eSEd Maste section_base = sh.sh_addr; 362a85fe12eSEd Maste } else if (eh.e_type == ET_REL) { 363a85fe12eSEd Maste /* 364a85fe12eSEd Maste * For relocatables, section base is the 365a85fe12eSEd Maste * relative offset of the specified section 366a85fe12eSEd Maste * to the start of the first section. 367a85fe12eSEd Maste */ 368a85fe12eSEd Maste section_base = off; 369a85fe12eSEd Maste } else 370a85fe12eSEd Maste warnx("unknown e_type %u", eh.e_type); 371a85fe12eSEd Maste return; 372a85fe12eSEd Maste } 373a85fe12eSEd Maste next: 374a85fe12eSEd Maste off += sh.sh_size; 375a85fe12eSEd Maste } 376a85fe12eSEd Maste elferr = elf_errno(); 377a85fe12eSEd Maste if (elferr != 0) 378a85fe12eSEd Maste warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 379a85fe12eSEd Maste 380a85fe12eSEd Maste errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); 381a85fe12eSEd Maste } 382a85fe12eSEd Maste 383a85fe12eSEd Maste int 384a85fe12eSEd Maste main(int argc, char **argv) 385a85fe12eSEd Maste { 386a85fe12eSEd Maste Elf *e; 387a85fe12eSEd Maste Dwarf_Debug dbg; 388a85fe12eSEd Maste Dwarf_Error de; 389a85fe12eSEd Maste const char *exe, *section; 390a85fe12eSEd Maste char line[1024]; 391a85fe12eSEd Maste int fd, i, opt; 392a85fe12eSEd Maste 393a85fe12eSEd Maste exe = NULL; 394a85fe12eSEd Maste section = NULL; 395a85fe12eSEd Maste while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != 396a85fe12eSEd Maste -1) { 397a85fe12eSEd Maste switch (opt) { 398a85fe12eSEd Maste case 'b': 399a85fe12eSEd Maste /* ignored */ 400a85fe12eSEd Maste break; 401a85fe12eSEd Maste case 'C': 402a85fe12eSEd Maste demangle = 1; 403a85fe12eSEd Maste break; 404a85fe12eSEd Maste case 'e': 405a85fe12eSEd Maste exe = optarg; 406a85fe12eSEd Maste break; 407a85fe12eSEd Maste case 'f': 408a85fe12eSEd Maste func = 1; 409a85fe12eSEd Maste break; 410a85fe12eSEd Maste case 'j': 411a85fe12eSEd Maste section = optarg; 412a85fe12eSEd Maste break; 413a85fe12eSEd Maste case 's': 414a85fe12eSEd Maste base = 1; 415a85fe12eSEd Maste break; 416a85fe12eSEd Maste case 'H': 417a85fe12eSEd Maste usage(); 418a85fe12eSEd Maste case 'V': 419a85fe12eSEd Maste version(); 420a85fe12eSEd Maste default: 421a85fe12eSEd Maste usage(); 422a85fe12eSEd Maste } 423a85fe12eSEd Maste } 424a85fe12eSEd Maste 425a85fe12eSEd Maste argv += optind; 426a85fe12eSEd Maste argc -= optind; 427a85fe12eSEd Maste 428a85fe12eSEd Maste if (exe == NULL) 429a85fe12eSEd Maste exe = "a.out"; 430a85fe12eSEd Maste 431a85fe12eSEd Maste if ((fd = open(exe, O_RDONLY)) < 0) 432a85fe12eSEd Maste err(EXIT_FAILURE, "%s", exe); 433a85fe12eSEd Maste 434a85fe12eSEd Maste if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) 435a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); 436a85fe12eSEd Maste 437a85fe12eSEd Maste if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) 438a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); 439a85fe12eSEd Maste 440a85fe12eSEd Maste if (section) 441a85fe12eSEd Maste find_section_base(exe, e, section); 442a85fe12eSEd Maste else 443a85fe12eSEd Maste section_base = 0; 444a85fe12eSEd Maste 445a85fe12eSEd Maste if (argc > 0) 446a85fe12eSEd Maste for (i = 0; i < argc; i++) 447a85fe12eSEd Maste translate(dbg, argv[i]); 448a85fe12eSEd Maste else 449a7265433SEd Maste while (fgets(line, sizeof(line), stdin) != NULL) { 450a85fe12eSEd Maste translate(dbg, line); 451a7265433SEd Maste fflush(stdout); 452a7265433SEd Maste } 453a85fe12eSEd Maste 454a85fe12eSEd Maste dwarf_finish(dbg, &de); 455a85fe12eSEd Maste 456a85fe12eSEd Maste (void) elf_end(e); 457a85fe12eSEd Maste 458a85fe12eSEd Maste exit(0); 459a85fe12eSEd Maste } 460