1*a85fe12eSEd Maste /*- 2*a85fe12eSEd Maste * Copyright (c) 2009 Kai Wang 3*a85fe12eSEd Maste * All rights reserved. 4*a85fe12eSEd Maste * 5*a85fe12eSEd Maste * Redistribution and use in source and binary forms, with or without 6*a85fe12eSEd Maste * modification, are permitted provided that the following conditions 7*a85fe12eSEd Maste * are met: 8*a85fe12eSEd Maste * 1. Redistributions of source code must retain the above copyright 9*a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer. 10*a85fe12eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright 11*a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer in the 12*a85fe12eSEd Maste * documentation and/or other materials provided with the distribution. 13*a85fe12eSEd Maste * 14*a85fe12eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*a85fe12eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*a85fe12eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*a85fe12eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*a85fe12eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*a85fe12eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*a85fe12eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*a85fe12eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*a85fe12eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*a85fe12eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*a85fe12eSEd Maste * SUCH DAMAGE. 25*a85fe12eSEd Maste */ 26*a85fe12eSEd Maste 27*a85fe12eSEd Maste #include <sys/cdefs.h> 28*a85fe12eSEd Maste #include <sys/param.h> 29*a85fe12eSEd Maste #include <dwarf.h> 30*a85fe12eSEd Maste #include <err.h> 31*a85fe12eSEd Maste #include <fcntl.h> 32*a85fe12eSEd Maste #include <gelf.h> 33*a85fe12eSEd Maste #include <getopt.h> 34*a85fe12eSEd Maste #include <libdwarf.h> 35*a85fe12eSEd Maste #include <libelftc.h> 36*a85fe12eSEd Maste #include <libgen.h> 37*a85fe12eSEd Maste #include <stdio.h> 38*a85fe12eSEd Maste #include <stdlib.h> 39*a85fe12eSEd Maste #include <string.h> 40*a85fe12eSEd Maste 41*a85fe12eSEd Maste #include "_elftc.h" 42*a85fe12eSEd Maste 43*a85fe12eSEd Maste ELFTC_VCSID("$Id: addr2line.c 2185 2011-11-19 16:07:16Z jkoshy $"); 44*a85fe12eSEd Maste 45*a85fe12eSEd Maste static struct option longopts[] = { 46*a85fe12eSEd Maste {"target" , required_argument, NULL, 'b'}, 47*a85fe12eSEd Maste {"demangle", no_argument, NULL, 'C'}, 48*a85fe12eSEd Maste {"exe", required_argument, NULL, 'e'}, 49*a85fe12eSEd Maste {"functions", no_argument, NULL, 'f'}, 50*a85fe12eSEd Maste {"section", required_argument, NULL, 'j'}, 51*a85fe12eSEd Maste {"basename", no_argument, NULL, 's'}, 52*a85fe12eSEd Maste {"help", no_argument, NULL, 'H'}, 53*a85fe12eSEd Maste {"version", no_argument, NULL, 'V'}, 54*a85fe12eSEd Maste {NULL, 0, NULL, 0} 55*a85fe12eSEd Maste }; 56*a85fe12eSEd Maste static int demangle, func, base; 57*a85fe12eSEd Maste static char unknown[] = { '?', '?', '\0' }; 58*a85fe12eSEd Maste static Dwarf_Addr section_base; 59*a85fe12eSEd Maste 60*a85fe12eSEd Maste #define USAGE_MESSAGE "\ 61*a85fe12eSEd Maste Usage: %s [options] hexaddress...\n\ 62*a85fe12eSEd Maste Map program addresses to source file names and line numbers.\n\n\ 63*a85fe12eSEd Maste Options:\n\ 64*a85fe12eSEd Maste -b TGT | --target=TGT (Accepted but ignored).\n\ 65*a85fe12eSEd Maste -e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\ 66*a85fe12eSEd Maste -f | --functions Display function names.\n\ 67*a85fe12eSEd Maste -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ 68*a85fe12eSEd Maste -s | --basename Only show the base name for each file name.\n\ 69*a85fe12eSEd Maste -C | --demangle Demangle C++ names.\n\ 70*a85fe12eSEd Maste -H | --help Print a help message.\n\ 71*a85fe12eSEd Maste -V | --version Print a version identifier and exit.\n" 72*a85fe12eSEd Maste 73*a85fe12eSEd Maste static void 74*a85fe12eSEd Maste usage(void) 75*a85fe12eSEd Maste { 76*a85fe12eSEd Maste (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 77*a85fe12eSEd Maste exit(1); 78*a85fe12eSEd Maste } 79*a85fe12eSEd Maste 80*a85fe12eSEd Maste static void 81*a85fe12eSEd Maste version(void) 82*a85fe12eSEd Maste { 83*a85fe12eSEd Maste 84*a85fe12eSEd Maste fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 85*a85fe12eSEd Maste exit(0); 86*a85fe12eSEd Maste } 87*a85fe12eSEd Maste 88*a85fe12eSEd Maste static void 89*a85fe12eSEd Maste search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, 90*a85fe12eSEd Maste const char **rlt_func) 91*a85fe12eSEd Maste { 92*a85fe12eSEd Maste Dwarf_Die ret_die, spec_die; 93*a85fe12eSEd Maste Dwarf_Error de; 94*a85fe12eSEd Maste Dwarf_Half tag; 95*a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc; 96*a85fe12eSEd Maste Dwarf_Off ref; 97*a85fe12eSEd Maste Dwarf_Attribute sub_at, spec_at; 98*a85fe12eSEd Maste char *func0; 99*a85fe12eSEd Maste int ret; 100*a85fe12eSEd Maste 101*a85fe12eSEd Maste if (*rlt_func != NULL) 102*a85fe12eSEd Maste return; 103*a85fe12eSEd Maste 104*a85fe12eSEd Maste if (dwarf_tag(die, &tag, &de)) { 105*a85fe12eSEd Maste warnx("dwarf_tag: %s", dwarf_errmsg(de)); 106*a85fe12eSEd Maste goto cont_search; 107*a85fe12eSEd Maste } 108*a85fe12eSEd Maste if (tag == DW_TAG_subprogram) { 109*a85fe12eSEd Maste if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || 110*a85fe12eSEd Maste dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) 111*a85fe12eSEd Maste goto cont_search; 112*a85fe12eSEd Maste if (addr < lopc || addr >= hipc) 113*a85fe12eSEd Maste goto cont_search; 114*a85fe12eSEd Maste 115*a85fe12eSEd Maste /* Found it! */ 116*a85fe12eSEd Maste 117*a85fe12eSEd Maste *rlt_func = unknown; 118*a85fe12eSEd Maste ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); 119*a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 120*a85fe12eSEd Maste return; 121*a85fe12eSEd Maste if (ret == DW_DLV_OK) { 122*a85fe12eSEd Maste if (dwarf_formstring(sub_at, &func0, &de)) 123*a85fe12eSEd Maste *rlt_func = unknown; 124*a85fe12eSEd Maste else 125*a85fe12eSEd Maste *rlt_func = func0; 126*a85fe12eSEd Maste return; 127*a85fe12eSEd Maste } 128*a85fe12eSEd Maste 129*a85fe12eSEd Maste /* 130*a85fe12eSEd Maste * If DW_AT_name is not present, but DW_AT_specification is 131*a85fe12eSEd Maste * present, then probably the actual name is in the DIE 132*a85fe12eSEd Maste * referenced by DW_AT_specification. 133*a85fe12eSEd Maste */ 134*a85fe12eSEd Maste if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) 135*a85fe12eSEd Maste return; 136*a85fe12eSEd Maste if (dwarf_global_formref(spec_at, &ref, &de)) 137*a85fe12eSEd Maste return; 138*a85fe12eSEd Maste if (dwarf_offdie(dbg, ref, &spec_die, &de)) 139*a85fe12eSEd Maste return; 140*a85fe12eSEd Maste if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) 141*a85fe12eSEd Maste *rlt_func = unknown; 142*a85fe12eSEd Maste 143*a85fe12eSEd Maste return; 144*a85fe12eSEd Maste } 145*a85fe12eSEd Maste 146*a85fe12eSEd Maste cont_search: 147*a85fe12eSEd Maste 148*a85fe12eSEd Maste /* Search children. */ 149*a85fe12eSEd Maste ret = dwarf_child(die, &ret_die, &de); 150*a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 151*a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); 152*a85fe12eSEd Maste else if (ret == DW_DLV_OK) 153*a85fe12eSEd Maste search_func(dbg, ret_die, addr, rlt_func); 154*a85fe12eSEd Maste 155*a85fe12eSEd Maste /* Search sibling. */ 156*a85fe12eSEd Maste ret = dwarf_siblingof(dbg, die, &ret_die, &de); 157*a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 158*a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); 159*a85fe12eSEd Maste else if (ret == DW_DLV_OK) 160*a85fe12eSEd Maste search_func(dbg, ret_die, addr, rlt_func); 161*a85fe12eSEd Maste } 162*a85fe12eSEd Maste 163*a85fe12eSEd Maste static void 164*a85fe12eSEd Maste translate(Dwarf_Debug dbg, const char* addrstr) 165*a85fe12eSEd Maste { 166*a85fe12eSEd Maste Dwarf_Die die; 167*a85fe12eSEd Maste Dwarf_Line *lbuf; 168*a85fe12eSEd Maste Dwarf_Error de; 169*a85fe12eSEd Maste Dwarf_Half tag; 170*a85fe12eSEd Maste Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; 171*a85fe12eSEd Maste Dwarf_Signed lcount; 172*a85fe12eSEd Maste Dwarf_Addr lineaddr, plineaddr; 173*a85fe12eSEd Maste const char *funcname; 174*a85fe12eSEd Maste char *file, *file0, *pfile; 175*a85fe12eSEd Maste char demangled[1024]; 176*a85fe12eSEd Maste int i, ret; 177*a85fe12eSEd Maste 178*a85fe12eSEd Maste addr = strtoull(addrstr, NULL, 16); 179*a85fe12eSEd Maste addr += section_base; 180*a85fe12eSEd Maste lineno = 0; 181*a85fe12eSEd Maste file = unknown; 182*a85fe12eSEd Maste 183*a85fe12eSEd Maste while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 184*a85fe12eSEd Maste &de)) == DW_DLV_OK) { 185*a85fe12eSEd Maste die = NULL; 186*a85fe12eSEd Maste while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { 187*a85fe12eSEd Maste if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { 188*a85fe12eSEd Maste warnx("dwarf_tag failed: %s", 189*a85fe12eSEd Maste dwarf_errmsg(de)); 190*a85fe12eSEd Maste goto out; 191*a85fe12eSEd Maste } 192*a85fe12eSEd Maste /* XXX: What about DW_TAG_partial_unit? */ 193*a85fe12eSEd Maste if (tag == DW_TAG_compile_unit) 194*a85fe12eSEd Maste break; 195*a85fe12eSEd Maste } 196*a85fe12eSEd Maste if (die == NULL) { 197*a85fe12eSEd Maste warnx("could not find DW_TAG_compile_unit die"); 198*a85fe12eSEd Maste goto out; 199*a85fe12eSEd Maste } 200*a85fe12eSEd Maste if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && 201*a85fe12eSEd Maste !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { 202*a85fe12eSEd Maste /* 203*a85fe12eSEd Maste * Check if the address falls into the PC range of 204*a85fe12eSEd Maste * this CU. 205*a85fe12eSEd Maste */ 206*a85fe12eSEd Maste if (addr < lopc || addr >= hipc) 207*a85fe12eSEd Maste continue; 208*a85fe12eSEd Maste } 209*a85fe12eSEd Maste 210*a85fe12eSEd Maste if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { 211*a85fe12eSEd Maste warnx("dwarf_srclines: %s", dwarf_errmsg(de)); 212*a85fe12eSEd Maste goto out; 213*a85fe12eSEd Maste } 214*a85fe12eSEd Maste 215*a85fe12eSEd Maste plineaddr = ~0ULL; 216*a85fe12eSEd Maste plineno = 0; 217*a85fe12eSEd Maste pfile = unknown; 218*a85fe12eSEd Maste for (i = 0; i < lcount; i++) { 219*a85fe12eSEd Maste if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { 220*a85fe12eSEd Maste warnx("dwarf_lineaddr: %s", 221*a85fe12eSEd Maste dwarf_errmsg(de)); 222*a85fe12eSEd Maste goto out; 223*a85fe12eSEd Maste } 224*a85fe12eSEd Maste if (dwarf_lineno(lbuf[i], &lineno, &de)) { 225*a85fe12eSEd Maste warnx("dwarf_lineno: %s", 226*a85fe12eSEd Maste dwarf_errmsg(de)); 227*a85fe12eSEd Maste goto out; 228*a85fe12eSEd Maste } 229*a85fe12eSEd Maste if (dwarf_linesrc(lbuf[i], &file0, &de)) { 230*a85fe12eSEd Maste warnx("dwarf_linesrc: %s", 231*a85fe12eSEd Maste dwarf_errmsg(de)); 232*a85fe12eSEd Maste } else 233*a85fe12eSEd Maste file = file0; 234*a85fe12eSEd Maste if (addr == lineaddr) 235*a85fe12eSEd Maste goto out; 236*a85fe12eSEd Maste else if (addr < lineaddr && addr > plineaddr) { 237*a85fe12eSEd Maste lineno = plineno; 238*a85fe12eSEd Maste file = pfile; 239*a85fe12eSEd Maste goto out; 240*a85fe12eSEd Maste } 241*a85fe12eSEd Maste plineaddr = lineaddr; 242*a85fe12eSEd Maste plineno = lineno; 243*a85fe12eSEd Maste pfile = file; 244*a85fe12eSEd Maste } 245*a85fe12eSEd Maste } 246*a85fe12eSEd Maste 247*a85fe12eSEd Maste out: 248*a85fe12eSEd Maste funcname = NULL; 249*a85fe12eSEd Maste if (ret == DW_DLV_OK && func) 250*a85fe12eSEd Maste search_func(dbg, die, addr, &funcname); 251*a85fe12eSEd Maste 252*a85fe12eSEd Maste if (func) { 253*a85fe12eSEd Maste if (funcname == NULL) 254*a85fe12eSEd Maste funcname = unknown; 255*a85fe12eSEd Maste if (demangle && 256*a85fe12eSEd Maste !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) 257*a85fe12eSEd Maste printf("%s\n", demangled); 258*a85fe12eSEd Maste else 259*a85fe12eSEd Maste printf("%s\n", funcname); 260*a85fe12eSEd Maste } 261*a85fe12eSEd Maste 262*a85fe12eSEd Maste (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); 263*a85fe12eSEd Maste 264*a85fe12eSEd Maste /* 265*a85fe12eSEd Maste * Reset internal CU pointer, so we will start from the first CU 266*a85fe12eSEd Maste * next round. 267*a85fe12eSEd Maste */ 268*a85fe12eSEd Maste while (ret != DW_DLV_NO_ENTRY) { 269*a85fe12eSEd Maste if (ret == DW_DLV_ERROR) 270*a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", 271*a85fe12eSEd Maste dwarf_errmsg(de)); 272*a85fe12eSEd Maste ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, 273*a85fe12eSEd Maste &de); 274*a85fe12eSEd Maste } 275*a85fe12eSEd Maste } 276*a85fe12eSEd Maste 277*a85fe12eSEd Maste static void 278*a85fe12eSEd Maste find_section_base(const char *exe, Elf *e, const char *section) 279*a85fe12eSEd Maste { 280*a85fe12eSEd Maste Dwarf_Addr off; 281*a85fe12eSEd Maste Elf_Scn *scn; 282*a85fe12eSEd Maste GElf_Ehdr eh; 283*a85fe12eSEd Maste GElf_Shdr sh; 284*a85fe12eSEd Maste size_t shstrndx; 285*a85fe12eSEd Maste int elferr; 286*a85fe12eSEd Maste const char *name; 287*a85fe12eSEd Maste 288*a85fe12eSEd Maste if (gelf_getehdr(e, &eh) != &eh) { 289*a85fe12eSEd Maste warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 290*a85fe12eSEd Maste return; 291*a85fe12eSEd Maste } 292*a85fe12eSEd Maste 293*a85fe12eSEd Maste if (!elf_getshstrndx(e, &shstrndx)) { 294*a85fe12eSEd Maste warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 295*a85fe12eSEd Maste return; 296*a85fe12eSEd Maste } 297*a85fe12eSEd Maste 298*a85fe12eSEd Maste (void) elf_errno(); 299*a85fe12eSEd Maste off = 0; 300*a85fe12eSEd Maste scn = NULL; 301*a85fe12eSEd Maste while ((scn = elf_nextscn(e, scn)) != NULL) { 302*a85fe12eSEd Maste if (gelf_getshdr(scn, &sh) == NULL) { 303*a85fe12eSEd Maste warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 304*a85fe12eSEd Maste continue; 305*a85fe12eSEd Maste } 306*a85fe12eSEd Maste if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) 307*a85fe12eSEd Maste goto next; 308*a85fe12eSEd Maste if (!strcmp(section, name)) { 309*a85fe12eSEd Maste if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { 310*a85fe12eSEd Maste /* 311*a85fe12eSEd Maste * For executables, section base is the virtual 312*a85fe12eSEd Maste * address of the specified section. 313*a85fe12eSEd Maste */ 314*a85fe12eSEd Maste section_base = sh.sh_addr; 315*a85fe12eSEd Maste } else if (eh.e_type == ET_REL) { 316*a85fe12eSEd Maste /* 317*a85fe12eSEd Maste * For relocatables, section base is the 318*a85fe12eSEd Maste * relative offset of the specified section 319*a85fe12eSEd Maste * to the start of the first section. 320*a85fe12eSEd Maste */ 321*a85fe12eSEd Maste section_base = off; 322*a85fe12eSEd Maste } else 323*a85fe12eSEd Maste warnx("unknown e_type %u", eh.e_type); 324*a85fe12eSEd Maste return; 325*a85fe12eSEd Maste } 326*a85fe12eSEd Maste next: 327*a85fe12eSEd Maste off += sh.sh_size; 328*a85fe12eSEd Maste } 329*a85fe12eSEd Maste elferr = elf_errno(); 330*a85fe12eSEd Maste if (elferr != 0) 331*a85fe12eSEd Maste warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 332*a85fe12eSEd Maste 333*a85fe12eSEd Maste errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); 334*a85fe12eSEd Maste } 335*a85fe12eSEd Maste 336*a85fe12eSEd Maste int 337*a85fe12eSEd Maste main(int argc, char **argv) 338*a85fe12eSEd Maste { 339*a85fe12eSEd Maste Elf *e; 340*a85fe12eSEd Maste Dwarf_Debug dbg; 341*a85fe12eSEd Maste Dwarf_Error de; 342*a85fe12eSEd Maste const char *exe, *section; 343*a85fe12eSEd Maste char line[1024]; 344*a85fe12eSEd Maste int fd, i, opt; 345*a85fe12eSEd Maste 346*a85fe12eSEd Maste exe = NULL; 347*a85fe12eSEd Maste section = NULL; 348*a85fe12eSEd Maste while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != 349*a85fe12eSEd Maste -1) { 350*a85fe12eSEd Maste switch (opt) { 351*a85fe12eSEd Maste case 'b': 352*a85fe12eSEd Maste /* ignored */ 353*a85fe12eSEd Maste break; 354*a85fe12eSEd Maste case 'C': 355*a85fe12eSEd Maste demangle = 1; 356*a85fe12eSEd Maste break; 357*a85fe12eSEd Maste case 'e': 358*a85fe12eSEd Maste exe = optarg; 359*a85fe12eSEd Maste break; 360*a85fe12eSEd Maste case 'f': 361*a85fe12eSEd Maste func = 1; 362*a85fe12eSEd Maste break; 363*a85fe12eSEd Maste case 'j': 364*a85fe12eSEd Maste section = optarg; 365*a85fe12eSEd Maste break; 366*a85fe12eSEd Maste case 's': 367*a85fe12eSEd Maste base = 1; 368*a85fe12eSEd Maste break; 369*a85fe12eSEd Maste case 'H': 370*a85fe12eSEd Maste usage(); 371*a85fe12eSEd Maste case 'V': 372*a85fe12eSEd Maste version(); 373*a85fe12eSEd Maste default: 374*a85fe12eSEd Maste usage(); 375*a85fe12eSEd Maste } 376*a85fe12eSEd Maste } 377*a85fe12eSEd Maste 378*a85fe12eSEd Maste argv += optind; 379*a85fe12eSEd Maste argc -= optind; 380*a85fe12eSEd Maste 381*a85fe12eSEd Maste if (exe == NULL) 382*a85fe12eSEd Maste exe = "a.out"; 383*a85fe12eSEd Maste 384*a85fe12eSEd Maste if ((fd = open(exe, O_RDONLY)) < 0) 385*a85fe12eSEd Maste err(EXIT_FAILURE, "%s", exe); 386*a85fe12eSEd Maste 387*a85fe12eSEd Maste if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) 388*a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); 389*a85fe12eSEd Maste 390*a85fe12eSEd Maste if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) 391*a85fe12eSEd Maste errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); 392*a85fe12eSEd Maste 393*a85fe12eSEd Maste if (section) 394*a85fe12eSEd Maste find_section_base(exe, e, section); 395*a85fe12eSEd Maste else 396*a85fe12eSEd Maste section_base = 0; 397*a85fe12eSEd Maste 398*a85fe12eSEd Maste if (argc > 0) 399*a85fe12eSEd Maste for (i = 0; i < argc; i++) 400*a85fe12eSEd Maste translate(dbg, argv[i]); 401*a85fe12eSEd Maste else 402*a85fe12eSEd Maste while (fgets(line, sizeof(line), stdin) != NULL) 403*a85fe12eSEd Maste translate(dbg, line); 404*a85fe12eSEd Maste 405*a85fe12eSEd Maste dwarf_finish(dbg, &de); 406*a85fe12eSEd Maste 407*a85fe12eSEd Maste (void) elf_end(e); 408*a85fe12eSEd Maste 409*a85fe12eSEd Maste exit(0); 410*a85fe12eSEd Maste } 411