00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "config.h"
00042 #include "libdwarfdefs.h"
00043 #ifdef HAVE_ELF_H
00044 #include <elf.h>
00045 #endif
00046 #include <dwarf.h>
00047 #include <libdwarf.h>
00048 #include "dwarf_base_types.h"
00049 #include "dwarf_alloc.h"
00050 #include "dwarf_opaque.h"
00051 #include "dwarf_arange.h"
00052 #include "dwarf_line.h"
00053 #include "dwarf_frame.h"
00054 #include <cmplrs/dwarf_addr_finder.h>
00055 #include "dwarf_error.h"
00056
00057 typedef unsigned long long ull;
00058
00059 static int do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die,
00060 int *errval);
00061 static int
00062 handle_debug_info(Dwarf_Debug dbg, int *errval);
00063 static int
00064 handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval);
00065 static int
00066 handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func, int *errval);
00067 static int
00068 handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_addr_callback_func cb_func, int *errval);
00069 static int
00070 handle_debug_loc(void);
00071
00072
00073 static Dwarf_addr_callback_func send_addr_note;
00074
00075 int
00076 _dwarf_addr_finder(dwarf_elf_handle elf_file_ptr,
00077 Dwarf_addr_callback_func cb_func, int *dwerr)
00078 {
00079
00080 Dwarf_Error err = 0;
00081 Dwarf_Debug dbg = 0;
00082 int res = 0;
00083 int errval = 0;
00084 int sections_found = 0;
00085
00086 res = dwarf_elf_init(elf_file_ptr, DW_DLC_READ, 0,
00087 0, &dbg, &err);
00088 if (res == DW_DLV_ERROR) {
00089 int errv = (int) dwarf_errno(err);
00090
00091 return errv;
00092 }
00093 if (res == DW_DLV_NO_ENTRY) {
00094 return res;
00095 }
00096
00097 send_addr_note = cb_func;
00098
00099 res = handle_debug_info(dbg, &errval);
00100 switch (res) {
00101 case DW_DLV_OK:
00102 ++sections_found;
00103 break;
00104 case DW_DLV_NO_ENTRY:
00105
00106 break;
00107 default:
00108 case DW_DLV_ERROR:
00109 dwarf_finish(dbg, &err);
00110 *dwerr = errval;
00111 return res;
00112 }
00113
00114 res = handle_debug_aranges(dbg, cb_func, &errval);
00115 switch (res) {
00116 case DW_DLV_OK:
00117 ++sections_found;
00118 break;
00119 case DW_DLV_NO_ENTRY:
00120 break;
00121 default:
00122 case DW_DLV_ERROR:
00123 dwarf_finish(dbg, &err);
00124 *dwerr = errval;
00125 return res;
00126 }
00127 res = handle_debug_frame(dbg, cb_func, &errval);
00128 switch (res) {
00129 case DW_DLV_OK:
00130 ++sections_found;
00131 break;
00132 case DW_DLV_NO_ENTRY:
00133 break;
00134 default:
00135 case DW_DLV_ERROR:
00136 dwarf_finish(dbg, &err);
00137 *dwerr = errval;
00138 return res;
00139 }
00140
00141 res = handle_debug_loc();
00142 switch (res) {
00143 case DW_DLV_OK:
00144 ++sections_found;
00145 break;
00146 case DW_DLV_NO_ENTRY:
00147 break;
00148 default:
00149 case DW_DLV_ERROR:
00150
00151 dwarf_finish(dbg, &err);
00152 *dwerr = errval;
00153 return res;
00154 }
00155
00156
00157
00158 *dwerr = 0;
00159 res = dwarf_finish(dbg, &err);
00160 if (res == DW_DLV_ERROR) {
00161 *dwerr = (int) dwarf_errno(err);
00162 return DW_DLV_ERROR;
00163 }
00164 if (sections_found == 0) {
00165 return DW_DLV_NO_ENTRY;
00166 }
00167 return DW_DLV_OK;
00168
00169 }
00170
00171
00172
00173
00174 static int
00175 handle_debug_info(Dwarf_Debug dbg, int *errval)
00176 {
00177 Dwarf_Unsigned nxtoff = 1;
00178 Dwarf_Unsigned hdr_length;
00179 Dwarf_Half version_stamp;
00180 Dwarf_Unsigned abbrev_offset;
00181 Dwarf_Half addr_size;
00182 Dwarf_Error err;
00183 int terminate_now = 0;
00184 int res = 0;
00185 Dwarf_Die sibdie;
00186 int sibres;
00187 int nres = DW_DLV_OK;
00188
00189
00190 for (nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
00191 &abbrev_offset,
00192 &addr_size, &nxtoff, &err);
00193 terminate_now == 0 && nres == DW_DLV_OK;
00194 nres = dwarf_next_cu_header(dbg, &hdr_length, &version_stamp,
00195 &abbrev_offset,
00196 &addr_size, &nxtoff, &err)
00197 ) {
00198
00199 Dwarf_Die curdie = 0;
00200
00201
00202 sibres = dwarf_siblingof(dbg, curdie, &sibdie, &err);
00203 if (sibres == DW_DLV_OK) {
00204 res = do_this_die_and_dealloc(dbg, sibdie, errval);
00205 switch (res) {
00206 case DW_DLV_OK:
00207 break;
00208 case DW_DLV_NO_ENTRY:
00209 break;
00210 default:
00211 case DW_DLV_ERROR:
00212 return DW_DLV_ERROR;
00213 }
00214 } else if (sibres == DW_DLV_ERROR) {
00215 *errval = (int) dwarf_errno(err);
00216 return DW_DLV_ERROR;
00217 } else {
00218
00219
00220 }
00221
00222 }
00223 if (nres == DW_DLV_ERROR) {
00224 int localerr = (int) dwarf_errno(err);
00225
00226 *errval = localerr;
00227 return DW_DLV_ERROR;
00228 }
00229 return DW_DLV_OK;
00230 }
00231
00232 static int
00233 might_have_addr[] = {
00234 DW_AT_high_pc,
00235 DW_AT_low_pc,
00236 };
00237 static int
00238 might_have_locdesc[] = {
00239 DW_AT_segment,
00240 DW_AT_return_addr,
00241 DW_AT_frame_base,
00242 DW_AT_static_link,
00243 DW_AT_data_member_location,
00244 DW_AT_string_length,
00245 DW_AT_location,
00246 DW_AT_use_location,
00247 DW_AT_vtable_elem_location,
00248 };
00249
00250
00251
00252
00253 static int
00254 handle_attr_addr(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
00255 Dwarf_Error * perr)
00256 {
00257 int res = DW_DLV_OK;
00258 Dwarf_Off offset;
00259 Dwarf_Addr addr;
00260 Dwarf_Half form;
00261 int ares;
00262
00263 Dwarf_Attribute attr;
00264
00265 ares = dwarf_attr(die, attrnum, &attr, perr);
00266 if (ares == DW_DLV_OK) {
00267 int formres = dwarf_whatform(attr, &form, perr);
00268
00269 switch (formres) {
00270 case DW_DLV_OK:
00271 break;
00272 case DW_DLV_ERROR:
00273 case DW_DLV_NO_ENTRY:
00274 return formres;
00275
00276 }
00277
00278 switch (form) {
00279 case DW_FORM_ref_addr:
00280 case DW_FORM_addr:
00281 res = dwarf_attr_offset(die, attr, &offset, perr);
00282 if (res == DW_DLV_OK) {
00283 ares = dwarf_formaddr(attr, &addr, perr);
00284 if (ares == DW_DLV_OK) {
00285 send_addr_note(DW_SECTION_INFO, offset, addr);
00286 } else if (ares == DW_DLV_ERROR) {
00287 return ares;
00288 }
00289 } else {
00290 res = DW_DLV_ERROR;
00291 }
00292 break;
00293
00294 default:
00295
00296
00297 ;
00298 }
00299 dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
00300
00301 } else {
00302 res = ares;
00303 }
00304 return res;
00305 }
00306
00307
00308
00309
00310 static int
00311 handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum,
00312 Dwarf_Error * perr)
00313 {
00314 int retval = DW_DLV_OK;
00315 Dwarf_Attribute attr;
00316 Dwarf_Locdesc *llbuf;
00317 Dwarf_Signed i;
00318 Dwarf_Off offset;
00319 Dwarf_Loc *locp;
00320 unsigned int entindx;
00321 int res;
00322 int ares;
00323
00324
00325 ares = dwarf_attr(die, attrnum, &attr, perr);
00326 if (ares == DW_DLV_OK) {
00327 Dwarf_Half form;
00328 int fres = dwarf_whatform(attr, &form, perr);
00329
00330 if (fres == DW_DLV_OK) {
00331 switch (form) {
00332 case DW_FORM_block1:
00333 case DW_FORM_block2:
00334 case DW_FORM_block4:
00335
00336 res = dwarf_attr_offset(die, attr, &offset, perr);
00337 llbuf = 0;
00338 if (res == DW_DLV_OK) {
00339 Dwarf_Signed count;
00340 int lres =
00341 dwarf_loclist(attr, &llbuf, &count, perr);
00342 if (lres != DW_DLV_OK) {
00343 return lres;
00344 }
00345 if (count != 1) {
00346
00347
00348 _dwarf_error(dbg, perr,
00349 DW_DLE_LOCDESC_COUNT_WRONG);
00350 retval = DW_DLV_ERROR;
00351 return retval;
00352 }
00353 for (i = 0; i < count; ++i) {
00354 unsigned int ents = llbuf[i].ld_cents;
00355
00356 locp = llbuf[i].ld_s;
00357 for (entindx = 0; entindx < ents; entindx++) {
00358 Dwarf_Loc *llocp;
00359
00360 llocp = locp + entindx;
00361 if (llocp->lr_atom == DW_OP_addr) {
00362 send_addr_note(DW_SECTION_INFO, offset +
00363 llocp->lr_offset + 1
00364
00365
00366
00367
00368 , llocp->lr_number);
00369 }
00370 }
00371 }
00372
00373
00374 if (count > 0) {
00375 for (i = 0; i < count; ++i) {
00376 dwarf_dealloc(dbg, llbuf[i].ld_s,
00377 DW_DLA_LOC_BLOCK);
00378 }
00379 dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
00380 }
00381 } else {
00382 retval = res;
00383 }
00384 break;
00385
00386 default:
00387
00388 ;
00389 }
00390 dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
00391 }
00392 retval = fres;
00393 } else {
00394 retval = ares;
00395 }
00396 return retval;
00397 }
00398
00399
00400
00401
00402
00403
00404 static int
00405 process_this_die_attrs(Dwarf_Debug dbg, Dwarf_Die newdie, int *errval)
00406 {
00407 Dwarf_Error err;
00408 Dwarf_Half i;
00409 Dwarf_Half newattrnum;
00410 int res;
00411 int tres;
00412 Dwarf_Half ltag;
00413
00414 Dwarf_Off doff;
00415 int doffres = dwarf_dieoffset(newdie, &doff, &err);
00416
00417 if (doffres != DW_DLV_OK) {
00418 if (doffres == DW_DLV_ERROR) {
00419 *errval = (int) dwarf_errno(err);
00420 }
00421 return doffres;
00422 }
00423 tres = dwarf_tag(newdie, <ag, &err);
00424 if (tres != DW_DLV_OK) {
00425 return tres;
00426 }
00427 if (DW_TAG_compile_unit == ltag) {
00428
00429
00430
00431
00432
00433 int lres;
00434
00435 lres = handle_debug_line(dbg, newdie, send_addr_note, errval);
00436 if (lres == DW_DLV_ERROR) {
00437 return lres;
00438 }
00439 }
00440
00441 for (i = 0; i < sizeof(might_have_addr) / sizeof(int); i++) {
00442 int resattr;
00443 Dwarf_Bool hasattr;
00444
00445 newattrnum = might_have_addr[i];
00446 err = 0;
00447 resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
00448 if (DW_DLV_OK == resattr) {
00449 if (hasattr) {
00450 res = handle_attr_addr(dbg, newdie, newattrnum, &err);
00451 if (res != DW_DLV_OK) {
00452 *errval = (int) dwarf_errno(err);
00453 return DW_DLV_ERROR;
00454 }
00455 }
00456 } else {
00457 if (resattr == DW_DLV_ERROR) {
00458 *errval = (int) dwarf_errno(err);
00459 return resattr;
00460 }
00461 }
00462 }
00463 for (i = 0; i < sizeof(might_have_locdesc) / sizeof(int); i++) {
00464 int resattr;
00465 Dwarf_Bool hasattr;
00466
00467 newattrnum = might_have_locdesc[i];
00468 err = 0;
00469 resattr = dwarf_hasattr(newdie, newattrnum, &hasattr, &err);
00470 if (DW_DLV_OK == resattr) {
00471 if (hasattr) {
00472 res =
00473 handle_attr_locdesc(dbg, newdie, newattrnum, &err);
00474 if (res != DW_DLV_OK) {
00475 *errval = (int) dwarf_errno(err);
00476 return DW_DLV_ERROR;
00477 }
00478 }
00479 } else {
00480 if (resattr == DW_DLV_ERROR) {
00481 *errval = (int) dwarf_errno(err);
00482 return resattr;
00483 }
00484 }
00485 }
00486
00487 return DW_DLV_OK;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 static int
00503 do_this_die_and_dealloc(Dwarf_Debug dbg, Dwarf_Die die, int *errval)
00504 {
00505
00506 Dwarf_Die prevdie = 0;
00507 Dwarf_Die newdie = die;
00508 Dwarf_Error err = 0;
00509 int res = 0;
00510 int sibres = DW_DLV_OK;
00511 int tres = DW_DLV_OK;
00512 Dwarf_Die sibdie;
00513
00514 while (sibres == DW_DLV_OK) {
00515 Dwarf_Die ch_die;
00516
00517
00518 res = process_this_die_attrs(dbg, newdie, errval);
00519 switch (res) {
00520 case DW_DLV_OK:
00521 break;
00522 case DW_DLV_NO_ENTRY:
00523 break;
00524 default:
00525 case DW_DLV_ERROR:
00526 if (prevdie) {
00527 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
00528 prevdie = 0;
00529 }
00530 return DW_DLV_ERROR;
00531 }
00532
00533 tres = dwarf_child(newdie, &ch_die, &err);
00534
00535 if (tres == DW_DLV_OK) {
00536 res = do_this_die_and_dealloc(dbg, ch_die, errval);
00537 switch (res) {
00538 case DW_DLV_OK:
00539 break;
00540 case DW_DLV_NO_ENTRY:
00541 break;
00542 default:
00543 case DW_DLV_ERROR:
00544 if (prevdie) {
00545 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
00546 prevdie = 0;
00547 }
00548 return DW_DLV_ERROR;
00549 }
00550 } else if (tres == DW_DLV_ERROR) {
00551
00552 *errval = (int) dwarf_errno(err);
00553 if (prevdie) {
00554 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
00555 prevdie = 0;
00556 }
00557 dwarf_dealloc(dbg, err, DW_DLA_ERROR);
00558 return DW_DLV_ERROR;
00559 }
00560 prevdie = newdie;
00561 sibdie = 0;
00562 sibres = dwarf_siblingof(dbg, newdie, &sibdie, &err);
00563 if (prevdie) {
00564 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
00565 prevdie = 0;
00566 }
00567 newdie = sibdie;
00568
00569 }
00570 if (sibres == DW_DLV_NO_ENTRY) {
00571 return DW_DLV_OK;
00572 }
00573
00574 *errval = (int) dwarf_errno(err);
00575 if (prevdie) {
00576 dwarf_dealloc(dbg, prevdie, DW_DLA_DIE);
00577 prevdie = 0;
00578 }
00579 dwarf_dealloc(dbg, err, DW_DLA_ERROR);
00580 return DW_DLV_ERROR;
00581
00582 }
00583
00584
00585 static int
00586 handle_debug_frame(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
00587 int *errval)
00588 {
00589 int retval = DW_DLV_OK;
00590 int res;
00591 Dwarf_Error err;
00592 Dwarf_Addr *addrlist;
00593 Dwarf_Off *offsetlist;
00594 Dwarf_Signed count;
00595 int i;
00596
00597 res =
00598 _dwarf_frame_address_offsets(dbg, &addrlist, &offsetlist,
00599 &count, &err);
00600 if (res == DW_DLV_OK) {
00601 for (i = 0; i < count; i++) {
00602 cb_func(DW_SECTION_FRAME, offsetlist[i], addrlist[i]);
00603 }
00604 dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
00605 dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
00606 } else if (res == DW_DLV_NO_ENTRY) {
00607 retval = res;
00608 } else {
00609 *errval = (int) dwarf_errno(err);
00610 retval = DW_DLV_ERROR;
00611 }
00612 return retval;
00613
00614 }
00615 static int
00616 handle_debug_aranges(Dwarf_Debug dbg, Dwarf_addr_callback_func cb_func,
00617 int *errval)
00618 {
00619 int retval = DW_DLV_OK;
00620 Dwarf_Error err;
00621 Dwarf_Addr *aranges;
00622 Dwarf_Signed count;
00623 int indx;
00624 Dwarf_Off *offsets;
00625
00626 retval =
00627 _dwarf_get_aranges_addr_offsets(dbg, &aranges, &offsets, &count,
00628 &err);
00629 if (retval == DW_DLV_OK) {
00630 if (count == 0) {
00631 retval = DW_DLV_NO_ENTRY;
00632 } else {
00633 for (indx = 0; indx < count; indx++) {
00634 cb_func(DW_SECTION_ARANGES, offsets[indx],
00635 aranges[indx]);
00636 }
00637 }
00638 dwarf_dealloc(dbg, aranges, DW_DLA_ADDR);
00639 dwarf_dealloc(dbg, offsets, DW_DLA_ADDR);
00640 } else if (retval == DW_DLV_NO_ENTRY) {
00641 ;
00642 } else {
00643 *errval = (int) dwarf_errno(err);
00644 retval = DW_DLV_ERROR;
00645 }
00646 return retval;
00647 }
00648 static int
00649 handle_debug_line(Dwarf_Debug dbg, Dwarf_Die cu_die,
00650 Dwarf_addr_callback_func cb_func, int *errval)
00651 {
00652 int retval = DW_DLV_OK;
00653 int res;
00654 Dwarf_Error err;
00655 Dwarf_Addr *addrlist;
00656 Dwarf_Off *offsetlist;
00657 Dwarf_Unsigned count;
00658 Dwarf_Unsigned i;
00659
00660 res =
00661 _dwarf_line_address_offsets(dbg, cu_die, &addrlist, &offsetlist,
00662 &count, &err);
00663 if (res == DW_DLV_OK) {
00664 for (i = 0; i < count; i++) {
00665 cb_func(DW_SECTION_LINE, offsetlist[i], addrlist[i]);
00666
00667 }
00668 dwarf_dealloc(dbg, offsetlist, DW_DLA_ADDR);
00669 dwarf_dealloc(dbg, addrlist, DW_DLA_ADDR);
00670 } else if (res == DW_DLV_NO_ENTRY) {
00671 retval = res;
00672 } else {
00673 *errval = (int) dwarf_errno(err);
00674 retval = DW_DLV_ERROR;
00675 }
00676 return retval;
00677 }
00678
00679
00680
00681
00682
00683
00684 static int
00685 handle_debug_loc(void)
00686 {
00687 int retval = DW_DLV_NO_ENTRY;
00688
00689 return retval;
00690 }