1 /*
2 Copyright (C) 2010-2013 David Anderson. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of the example nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15 THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
16 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 */
27
28 // createirepfrombinary.cc
29
30 // Reads an object and inserts its dwarf data into
31 // an object intended to hold all the dwarf data.
32
33 #include "config.h"
34
35 /* Windows specific header files */
36 #ifdef HAVE_STDAFX_H
37 #include "stdafx.h"
38 #endif /* HAVE_STDAFX_H */
39
40 #include <unistd.h>
41 #include <stdlib.h> // for exit
42 #include <iostream>
43 #include <string>
44 #include <list>
45 #include <map>
46 #include <vector>
47 #include <string.h> // For memset etc
48 #include <sys/stat.h> //open
49 #include <fcntl.h> //open
50 #include "gelf.h"
51 #include "strtabdata.h"
52 #include "dwarf.h"
53 #include "libdwarf.h"
54 #include "irepresentation.h"
55 #include "createirepfrombinary.h"
56 #include "general.h" // For IToHex()
57
58 using std::string;
59 using std::cout;
60 using std::cerr;
61 using std::endl;
62 using std::vector;
63 using std::list;
64 using std::map;
65
66 static void readFrameDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
67 static void readMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
68 static void readCUDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep);
69 static void readGlobals(Dwarf_Debug dbg, IRepresentation & irep);
70
71 /* Use a generic call to open the file, due to issues with Windows */
72 extern int open_a_file(const char * name);
73 extern int create_a_file(const char * name);
74 extern void close_a_file(int f);
75
errprint(Dwarf_Error err)76 static void errprint(Dwarf_Error err)
77 {
78 cerr << "Error num: " << dwarf_errno(err) << " " << dwarf_errmsg(err) << endl;
79 };
80
81 class DbgInAutoCloser {
82 public:
DbgInAutoCloser(Dwarf_Debug dbg,int fd)83 DbgInAutoCloser(Dwarf_Debug dbg,int fd): dbg_(dbg),fd_(fd) {};
~DbgInAutoCloser()84 ~DbgInAutoCloser() {
85 Dwarf_Error err = 0;
86 dwarf_finish(dbg_,&err);
87 close(fd_);
88 };
89 private:
90 Dwarf_Debug dbg_;
91 int fd_;
92 };
93
94
95 void
createIrepFromBinary(const std::string & infile,IRepresentation & irep)96 createIrepFromBinary(const std::string &infile,
97 IRepresentation & irep)
98 {
99 Dwarf_Debug dbg = 0;
100 Dwarf_Error err;
101 int fd = open_a_file(infile.c_str());
102 if(fd < 0 ) {
103 cerr << "Unable to open " << infile <<
104 " for reading." << endl;
105 exit(1);
106 }
107 // All reader error handling is via the err argument.
108 int res = dwarf_init(fd,DW_DLC_READ,
109 0,
110 0,
111 &dbg,
112 &err);
113 if(res != DW_DLV_OK) {
114 close_a_file(fd);
115 cerr << "Error init-ing " << infile <<
116 " for reading." << endl;
117 exit(1);
118 }
119
120 DbgInAutoCloser closer(dbg,fd);
121
122 readFrameDataFromBinary(dbg,irep);
123 readCUDataFromBinary(dbg,irep);
124 readMacroDataFromBinary(dbg,irep);
125 readGlobals(dbg,irep);
126 return;
127 }
128
129 static void
readFrameDataFromBinary(Dwarf_Debug dbg,IRepresentation & irep)130 readFrameDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
131 {
132 Dwarf_Error err = 0;
133 Dwarf_Cie * cie_data = 0;
134 Dwarf_Signed cie_count = 0;
135 Dwarf_Fde * fde_data = 0;
136 Dwarf_Signed fde_count = 0;
137 int res = dwarf_get_fde_list(dbg,
138 &cie_data,
139 &cie_count,
140 &fde_data,
141 &fde_count,
142 &err);
143 if(res == DW_DLV_NO_ENTRY) {
144 // No frame data.
145 return;
146 }
147 if(res == DW_DLV_ERROR) {
148 cerr << "Error reading frame data " << endl;
149 exit(1);
150 }
151
152 for(Dwarf_Signed i =0; i < cie_count; ++i) {
153 Dwarf_Unsigned bytes_in_cie = 0;
154 Dwarf_Small version = 0;
155 char * augmentation = 0;
156 Dwarf_Unsigned code_alignment_factor = 0;
157 Dwarf_Signed data_alignment_factor = 0;
158 Dwarf_Half return_address_register_rule = 0;
159 Dwarf_Ptr initial_instructions = 0;
160 Dwarf_Unsigned initial_instructions_length = 0;
161 res = dwarf_get_cie_info(cie_data[i], &bytes_in_cie,
162 &version,&augmentation, &code_alignment_factor,
163 &data_alignment_factor,&return_address_register_rule,
164 &initial_instructions,&initial_instructions_length,
165 &err);
166 if(res != DW_DLV_OK) {
167 errprint(err);
168 cerr << "Error reading frame data cie index " << i << endl;
169 exit(1);
170 }
171 // Index in cie_data must match index in ciedata_, here
172 // correct by construction.
173 IRCie cie(bytes_in_cie,version,augmentation,code_alignment_factor,
174 data_alignment_factor,return_address_register_rule,
175 initial_instructions,initial_instructions_length);
176 irep.framedata().insert_cie(cie);
177 }
178 for(Dwarf_Signed i =0; i < fde_count; ++i) {
179 Dwarf_Addr low_pc = 0;
180 Dwarf_Unsigned func_length = 0;
181 Dwarf_Ptr fde_bytes = 0;
182 Dwarf_Unsigned fde_byte_length = 0;
183 Dwarf_Off cie_offset = 0;
184 Dwarf_Signed cie_index = 0;
185 Dwarf_Off fde_offset = 0;
186 res = dwarf_get_fde_range(fde_data[i], &low_pc,
187 &func_length,&fde_bytes, &fde_byte_length,
188 &cie_offset,&cie_index,
189 &fde_offset,
190 &err);
191 if(res != DW_DLV_OK) {
192 cerr << "Error reading frame data fde index " << i << endl;
193 exit(1);
194 }
195 IRFde fde(low_pc,func_length,fde_bytes,fde_byte_length,
196 cie_offset, cie_index,fde_offset);
197 Dwarf_Ptr instr_in = 0;
198 Dwarf_Unsigned instr_len = 0;
199 res = dwarf_get_fde_instr_bytes(fde_data[i],
200 &instr_in, &instr_len, &err);
201 if(res != DW_DLV_OK) {
202 cerr << "Error reading frame data fde instructions " << i << endl;
203 exit(1);
204 }
205 fde.get_fde_instrs_into_ir(instr_in,instr_len);
206 irep.framedata().insert_fde(fde);
207 }
208 dwarf_fde_cie_list_dealloc(dbg,cie_data,cie_count,
209 fde_data,fde_count);
210 }
211
212
213 static void
readCUMacroDataFromBinary(Dwarf_Debug dbg,IRepresentation & irep,Dwarf_Unsigned macrodataoffset,IRCUdata & cu)214 readCUMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep,
215 Dwarf_Unsigned macrodataoffset,IRCUdata &cu)
216 {
217 // Arbitrary, but way too high to be real!
218 // Probably should be lower.
219 Dwarf_Unsigned maxcount = 1000000000;
220 Dwarf_Error error;
221 Dwarf_Signed mcount=0;
222 Dwarf_Macro_Details *md = 0;
223 int res = dwarf_get_macro_details(dbg,macrodataoffset,
224 maxcount, &mcount, &md, &error);
225 if(res == DW_DLV_OK) {
226 IRMacro ¯odata = irep.macrodata();
227 vector<IRMacroRecord> mvec = macrodata.getMacroVec();
228 mvec.reserve(mcount);
229 Dwarf_Unsigned dieoffset = cu.baseDie().getGlobalOffset();
230 Dwarf_Macro_Details *mdp = md;
231 for(int i = 0; i < mcount; ++i, mdp++ ) {
232 IRMacroRecord ir(dieoffset,mdp->dmd_offset,
233 mdp->dmd_type, mdp->dmd_lineno,
234 mdp->dmd_fileindex, mdp->dmd_macro?mdp->dmd_macro:"");
235 mvec.push_back(ir);
236 }
237 }
238 dwarf_dealloc(dbg, md, DW_DLA_STRING);
239 }
240
241 void
get_basic_attr_data_one_attr(Dwarf_Debug dbg,Dwarf_Attribute attr,IRCUdata & cudata,IRAttr & irattr)242 get_basic_attr_data_one_attr(Dwarf_Debug dbg,
243 Dwarf_Attribute attr,IRCUdata &cudata,IRAttr & irattr)
244 {
245 Dwarf_Error error;
246 Dwarf_Half attrnum = 0;
247 Dwarf_Half finalform = 0;
248 Dwarf_Half initialform = 0;
249 int res = dwarf_whatattr(attr,&attrnum,&error);
250 if(res != DW_DLV_OK) {
251 errprint(error);
252 cerr << "Unable to get attr number " << endl;
253 exit(1);
254 }
255 res = dwarf_whatform(attr,&finalform,&error);
256 if(res != DW_DLV_OK) {
257 errprint(error);
258 cerr << "Unable to get attr form " << endl;
259 exit(1);
260 }
261
262 res = dwarf_whatform_direct(attr,&initialform,&error);
263 if(res != DW_DLV_OK) {
264 errprint(error);
265 cerr << "Unable to get attr direct form " << endl;
266 exit(1);
267 }
268 irattr.setBaseData(attrnum,finalform,initialform);
269 enum Dwarf_Form_Class cl = dwarf_get_form_class(
270 cudata.getVersionStamp(), attrnum,
271 cudata.getOffsetSize(), finalform);
272 irattr.setFormClass(cl);
273 if (cl == DW_FORM_CLASS_UNKNOWN) {
274 cerr << "Unable to figure out form class. ver " <<
275 cudata.getVersionStamp() <<
276 " attrnum " << attrnum <<
277 " offsetsize " << cudata.getOffsetSize() <<
278 " formnum " << finalform << endl;
279 return;
280 }
281 irattr.setFormData(formFactory(dbg,attr,cudata,irattr));
282 }
283 void
get_basic_die_data(Dwarf_Debug dbg,Dwarf_Die indie,IRDie & irdie)284 get_basic_die_data(Dwarf_Debug dbg,
285 Dwarf_Die indie,IRDie &irdie)
286 {
287 Dwarf_Half tagval = 0;
288 Dwarf_Error error = 0;
289 int res = dwarf_tag(indie,&tagval,&error);
290 if(res != DW_DLV_OK) {
291 errprint(error);
292 cerr << "Unable to get die tag "<< endl;
293 exit(1);
294 }
295 Dwarf_Off goff = 0;
296 res = dwarf_dieoffset(indie,&goff,&error);
297 if(res != DW_DLV_OK) {
298 errprint(error);
299 cerr << "Unable to get die offset "<< endl;
300 exit(1);
301 }
302 Dwarf_Off localoff = 0;
303 res = dwarf_die_CU_offset(indie,&localoff,&error);
304 if(res != DW_DLV_OK) {
305 errprint(error);
306 cerr << "Unable to get cu die offset "<< endl;
307 exit(1);
308 }
309 irdie.setBaseData(tagval,goff,localoff);
310 }
311
312
313 static void
get_attrs_of_die(Dwarf_Die in_die,IRDie & irdie,IRCUdata & cudata,IRepresentation & irep,Dwarf_Debug dbg)314 get_attrs_of_die(Dwarf_Die in_die,IRDie &irdie,
315 IRCUdata &cudata,
316 IRepresentation &irep,
317 Dwarf_Debug dbg)
318 {
319 Dwarf_Error error = 0;
320 Dwarf_Attribute *atlist = 0;
321 Dwarf_Signed atcnt = 0;
322 std::list<IRAttr> &attrlist = irdie.getAttributes();
323 int res = dwarf_attrlist(in_die, &atlist,&atcnt,&error);
324 if(res == DW_DLV_NO_ENTRY) {
325 return;
326 }
327 if(res == DW_DLV_ERROR) {
328 errprint(error);
329 cerr << "dwarf_attrlist failed " << endl;
330 exit(1);
331 }
332 for (Dwarf_Signed i = 0; i < atcnt; ++i) {
333 Dwarf_Attribute attr = atlist[i];
334 // Use an empty attr to get a placeholder on
335 // the attr list for this IRDie.
336 IRAttr irattr;
337 attrlist.push_back(irattr);
338 // We want a pointer to the final attr to be
339 // recorded for references, not a local temp IRAttr.
340 IRAttr & lastirattr = attrlist.back();
341 get_basic_attr_data_one_attr(dbg,attr,cudata,lastirattr);
342
343 }
344 dwarf_dealloc(dbg,atlist, DW_DLA_LIST);
345 }
346
347 // Invariant: IRDie and IRCUdata are in the irep tree,
348 // not local record references to local scopes.
349 static void
get_children_of_die(Dwarf_Die in_die,IRDie & irdie,IRCUdata & ircudata,IRepresentation & irep,Dwarf_Debug dbg)350 get_children_of_die(Dwarf_Die in_die,IRDie&irdie,
351 IRCUdata &ircudata,
352 IRepresentation &irep,
353 Dwarf_Debug dbg)
354 {
355 Dwarf_Die curchilddie = 0;
356 Dwarf_Error error = 0;
357 int res = dwarf_child(in_die,&curchilddie,&error);
358 if(res == DW_DLV_NO_ENTRY) {
359 return;
360 }
361 if(res == DW_DLV_ERROR) {
362 errprint(error);
363 cerr << "dwarf_child failed " << endl;
364 exit(1);
365 }
366 //std::list<IRDie> & childlist = irdie.getChildren();
367 int childcount = 0;
368 for(;;) {
369 IRDie child;
370 get_basic_die_data(dbg,curchilddie,child);
371 irdie.addChild(child);
372 IRDie &lastchild = irdie.lastChild();
373 get_attrs_of_die(curchilddie,lastchild,ircudata,irep,dbg);
374
375 ircudata.insertLocalDieOffset(lastchild.getCURelativeOffset(),
376 &lastchild);
377
378 get_children_of_die(curchilddie,lastchild,ircudata,irep,dbg);
379 ++childcount;
380
381 Dwarf_Die tchild = 0;
382 res = dwarf_siblingof(dbg,curchilddie,&tchild,&error);
383 if(res == DW_DLV_NO_ENTRY) {
384 break;
385 }
386 if(res == DW_DLV_ERROR) {
387 errprint(error);
388 cerr << "dwarf_siblingof failed " << endl;
389 exit(1);
390 }
391 dwarf_dealloc(dbg,curchilddie,DW_DLA_DIE);
392 curchilddie = tchild;
393 }
394 dwarf_dealloc(dbg,curchilddie,DW_DLA_DIE);
395 }
396
397 static void
get_linedata_of_cu_die(Dwarf_Die in_die,IRDie & irdie,IRCUdata & ircudata,IRepresentation & irep,Dwarf_Debug dbg)398 get_linedata_of_cu_die(Dwarf_Die in_die,IRDie&irdie,
399 IRCUdata &ircudata,
400 IRepresentation &irep,
401 Dwarf_Debug dbg)
402 {
403 Dwarf_Error error = 0;
404 char **srcfiles = 0;
405 Dwarf_Signed srccount = 0;
406 IRCULineData&culinesdata = ircudata.getCULines();
407 int res = dwarf_srcfiles(in_die,&srcfiles, &srccount,&error);
408 if(res == DW_DLV_ERROR) {
409 errprint(error);
410 cerr << "dwarf_srcfiles failed " << endl;
411 exit(1);
412 } else if (res == DW_DLV_NO_ENTRY) {
413 // No data.
414 return;
415 }
416
417 std::vector<IRCUSrcfile> &srcs = culinesdata.get_cu_srcfiles();
418 for (Dwarf_Signed i = 0; i < srccount; ++i) {
419 IRCUSrcfile S(srcfiles[i]);
420 srcs.push_back(S);
421 /* use srcfiles[i] */
422 dwarf_dealloc(dbg, srcfiles[i], DW_DLA_STRING);
423 }
424 dwarf_dealloc(dbg, srcfiles, DW_DLA_LIST);
425
426 Dwarf_Line * linebuf = 0;
427 Dwarf_Signed linecnt = 0;
428 int res2 = dwarf_srclines(in_die,&linebuf,&linecnt, &error);
429 if(res == DW_DLV_ERROR) {
430 errprint(error);
431 cerr << "dwarf_srclines failed " << endl;
432 exit(1);
433 } else if (res == DW_DLV_NO_ENTRY) {
434 // No data.
435 cerr << "dwarf_srclines failed NO_ENTRY, crazy "
436 "since srcfiles worked" << endl;
437 exit(1);
438 }
439
440 std::vector<IRCULine> &lines = culinesdata.get_cu_lines();
441 for(Dwarf_Signed j = 0; j < linecnt ; ++j ) {
442 Dwarf_Line li = linebuf[j];
443 int lres;
444
445 Dwarf_Addr address = 0;
446 lres = dwarf_lineaddr(li,&address,&error);
447 if (lres != DW_DLV_OK) {
448 cerr << "dwarf_lineaddr failed. " << endl;
449 exit(1);
450 }
451 Dwarf_Bool is_addr_set = 0;
452 lres = dwarf_line_is_addr_set(li,&is_addr_set,&error);
453 if (lres != DW_DLV_OK) {
454 cerr << "dwarf_line_is_addr_set failed. " << endl;
455 exit(1);
456 }
457 Dwarf_Unsigned fileno = 0;
458 lres = dwarf_line_srcfileno(li,&fileno,&error);
459 if (lres != DW_DLV_OK) {
460 cerr << "dwarf_srcfileno failed. " << endl;
461 exit(1);
462 }
463 Dwarf_Unsigned lineno = 0;
464 lres = dwarf_lineno(li,&lineno,&error);
465 if (lres != DW_DLV_OK) {
466 cerr << "dwarf_lineno failed. " << endl;
467 exit(1);
468 }
469 Dwarf_Unsigned lineoff = 0;
470 lres = dwarf_lineoff_b(li,&lineoff,&error);
471 if (lres != DW_DLV_OK) {
472 cerr << "dwarf_lineoff failed. " << endl;
473 exit(1);
474 }
475 char *linesrctmp = 0;
476 lres = dwarf_linesrc(li,&linesrctmp,&error);
477 if (lres != DW_DLV_OK) {
478 cerr << "dwarf_linesrc failed. " << endl;
479 exit(1);
480 }
481 // libdwarf is trying to generate a full path,
482 // the string here is that generated data, not
483 // simply the 'file' path represented by the
484 // file number (fileno).
485 std::string linesrc(linesrctmp);
486
487
488 Dwarf_Bool is_stmt = 0;
489 lres = dwarf_linebeginstatement(li,&is_stmt,&error);
490 if (lres != DW_DLV_OK) {
491 cerr << "dwarf_linebeginstatement failed. " << endl;
492 exit(1);
493 }
494
495 Dwarf_Bool basic_block = 0;
496 lres = dwarf_lineblock(li,&basic_block,&error);
497 if (lres != DW_DLV_OK) {
498 cerr << "dwarf_lineblock failed. " << endl;
499 exit(1);
500 }
501
502 Dwarf_Bool end_sequence = 0;
503 lres = dwarf_lineendsequence(li,&end_sequence,&error);
504 if (lres != DW_DLV_OK) {
505 cerr << "dwarf_lineendsequence failed. " << endl;
506 exit(1);
507 }
508
509 Dwarf_Bool prologue_end = 0;
510 Dwarf_Bool epilogue_begin = 0;
511 Dwarf_Unsigned isa = 0;
512 Dwarf_Unsigned discriminator = 0;
513 lres = dwarf_prologue_end_etc(li,&prologue_end,
514 &epilogue_begin,&isa,&discriminator,&error);
515 if (lres != DW_DLV_OK) {
516 cerr << "dwarf_prologue_end_etc failed. " << endl;
517 exit(1);
518 }
519
520 IRCULine L(address,
521 is_addr_set,
522 fileno,
523 lineno,
524 lineoff,
525 linesrc,
526 is_stmt,
527 basic_block,
528 end_sequence,
529 prologue_end,epilogue_begin,
530 isa,discriminator);
531 lines.push_back(L);
532 }
533 dwarf_srclines_dealloc(dbg, linebuf, linecnt);
534 }
535
536 static bool
getToplevelOffsetAttr(Dwarf_Die cu_die,Dwarf_Half attrnumber,Dwarf_Unsigned & offset_out)537 getToplevelOffsetAttr(Dwarf_Die cu_die,Dwarf_Half attrnumber,
538 Dwarf_Unsigned &offset_out)
539 {
540 Dwarf_Error error = 0;
541 Dwarf_Off offset = 0;
542 Dwarf_Attribute attr = 0;
543 int res = dwarf_attr(cu_die,attrnumber,&attr, &error);
544 bool foundit = false;
545 Dwarf_Off sectoff = 0;
546 if(res == DW_DLV_OK) {
547 Dwarf_Signed sval = 0;
548 Dwarf_Unsigned uval = 0;
549 res = dwarf_global_formref(attr,&offset,&error);
550 if(res == DW_DLV_OK) {
551 foundit = true;
552 offset_out = offset;
553 }
554 }
555 return foundit;
556 }
557
558 // We record the .debug_info info for each CU found
559 // To start with we restrict attention to very few DIEs and
560 // attributes, but intend to get all eventually.
561 static void
readCUDataFromBinary(Dwarf_Debug dbg,IRepresentation & irep)562 readCUDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
563 {
564 Dwarf_Error error;
565 int cu_number = 0;
566 std::list<IRCUdata> &culist = irep.infodata().getCUData();
567
568 for(;;++cu_number) {
569 Dwarf_Unsigned cu_header_length = 0;
570 Dwarf_Half version_stamp = 0;
571 Dwarf_Unsigned abbrev_offset = 0;
572 Dwarf_Half address_size = 0;
573 Dwarf_Unsigned next_cu_header = 0;
574 Dwarf_Half offset_size = 0;
575 Dwarf_Half extension_size = 0;
576 Dwarf_Die no_die = 0;
577 Dwarf_Die cu_die = 0;
578 int res = DW_DLV_ERROR;
579 res = dwarf_next_cu_header_b(dbg,&cu_header_length,
580 &version_stamp, &abbrev_offset, &address_size,
581 &offset_size, &extension_size,
582 &next_cu_header, &error);
583 if(res == DW_DLV_ERROR) {
584 errprint(error);
585 cerr <<"Error in dwarf_next_cu_header"<< endl;
586 exit(1);
587 }
588 if(res == DW_DLV_NO_ENTRY) {
589 /* Done. */
590 return;
591 }
592 IRCUdata cudata(cu_header_length,version_stamp,
593 abbrev_offset,address_size, offset_size,
594 extension_size,next_cu_header);
595
596 // The CU will have a single sibling (well, it is
597 // not exactly a sibling, but close enough), a cu_die.
598 res = dwarf_siblingof(dbg,no_die,&cu_die,&error);
599 if(res == DW_DLV_ERROR) {
600 errprint(error);
601 cerr <<"Error in dwarf_siblingof on CU die "<< endl;
602 exit(1);
603 }
604 if(res == DW_DLV_NO_ENTRY) {
605 /* Impossible case. */
606 cerr <<"no Entry! in dwarf_siblingof on CU die "<< endl;
607 exit(1);
608 }
609 Dwarf_Off macrooffset = 0;
610 bool foundmsect = getToplevelOffsetAttr(cu_die,DW_AT_macro_info,
611 macrooffset);
612 Dwarf_Off linesoffset = 0;
613 bool foundlines = getToplevelOffsetAttr(cu_die,DW_AT_stmt_list,
614 linesoffset);
615 Dwarf_Off dieoff = 0;
616 res = dwarf_dieoffset(cu_die,&dieoff,&error);
617 if(res != DW_DLV_OK) {
618 cerr << "Unable to get cu die offset for macro infomation "<< endl;
619 exit(1);
620 }
621 if(foundmsect) {
622 cudata.setMacroData(macrooffset,dieoff);
623 }
624 if(foundlines) {
625 cudata.setLineData(linesoffset,dieoff);
626 }
627 culist.push_back(cudata);
628 IRCUdata & treecu = irep.infodata().lastCU();
629 IRDie &cuirdie = treecu.baseDie();
630 get_basic_die_data(dbg,cu_die,cuirdie);
631 treecu.insertLocalDieOffset(cuirdie.getCURelativeOffset(),
632 &cuirdie);
633 get_attrs_of_die(cu_die,cuirdie,treecu,irep,dbg);
634 get_children_of_die(cu_die,cuirdie,treecu,irep,dbg);
635 get_linedata_of_cu_die(cu_die,cuirdie,treecu,irep,dbg);
636
637 // Now we have all local DIEs in the CU so we
638 // can identify all targets of local CLASS_REFERENCE
639 // and insert the IRDie * into the IRFormReference
640 treecu.updateReferenceAttrDieTargets();
641
642 dwarf_dealloc(dbg,cu_die,DW_DLA_DIE);
643 }
644 // If we want pointers from child to parent now is the time
645 // we can construct them.
646 }
647
648 // We read thru the CU headers and the CU die to find
649 // the macro info for each CU (if any).
650 // We record the CU macro info for each CU found (using
651 // the value of the DW_AT_macro_info attribute, if any).
652 static void
readMacroDataFromBinary(Dwarf_Debug dbg,IRepresentation & irep)653 readMacroDataFromBinary(Dwarf_Debug dbg, IRepresentation & irep)
654 {
655
656 list<IRCUdata> &cudata = irep.infodata().getCUData();
657 list<IRCUdata>::iterator it = cudata.begin();
658 int ct = 0;
659 for( ; it != cudata.end(); ++it,++ct) {
660 Dwarf_Unsigned macrooffset = 0;
661 Dwarf_Unsigned cudieoffset = 0;
662 bool foundmsect = it->hasMacroData(¯ooffset,&cudieoffset);
663 if(foundmsect) {
664 readCUMacroDataFromBinary(dbg, irep, macrooffset,*it);
665 }
666 }
667 }
668
669 // Offsets refer to .debug_info, nothing else.
670 static void
readGlobals(Dwarf_Debug dbg,IRepresentation & irep)671 readGlobals(Dwarf_Debug dbg, IRepresentation & irep)
672 {
673 Dwarf_Error error;
674 Dwarf_Global *globs = 0;
675 Dwarf_Type *types = 0;
676 Dwarf_Signed cnt = 0;
677 Dwarf_Signed i = 0;
678 int res = 0;
679 IRPubsData &pubdata = irep.pubnamedata();
680
681 res = dwarf_get_globals(dbg, &globs,&cnt, &error);
682 if(res == DW_DLV_OK) {
683 std::list<IRPub> &pubnames = pubdata.getPubnames();
684 for (Dwarf_Signed i = 0; i < cnt; ++i) {
685 Dwarf_Global g = globs[i];
686 char *name = 0;
687 // dieoff and cuoff may be in .debug_info
688 // or .debug_types
689 Dwarf_Off dieoff = 0;
690 Dwarf_Off cuoff = 0;
691 res = dwarf_global_name_offsets(g,&name,
692 &dieoff,&cuoff,&error);
693 if( res == DW_DLV_OK) {
694 IRPub p(name,dieoff,cuoff);
695 dwarf_dealloc(dbg,name,DW_DLA_STRING);
696 pubnames.push_back(p);
697 }
698 }
699 dwarf_globals_dealloc(dbg, globs, cnt);
700 } else if (res == DW_DLV_ERROR) {
701 cerr << "dwarf_get_globals failed" << endl;
702 exit(1);
703 }
704 res = dwarf_get_pubtypes(dbg, &types,&cnt, &error);
705 if(res == DW_DLV_OK) {
706 std::list<IRPub> &pubtypes = pubdata.getPubtypes();
707 for (Dwarf_Signed i = 0; i < cnt; ++i) {
708 Dwarf_Type g = types[i];
709 char *name = 0;
710 // dieoff and cuoff may be in .debug_info
711 // or .debug_types
712 Dwarf_Off dieoff = 0;
713 Dwarf_Off cuoff = 0;
714 res = dwarf_pubtype_name_offsets(g,&name,
715 &dieoff,&cuoff,&error);
716 if( res == DW_DLV_OK) {
717 IRPub p(name,dieoff,cuoff);
718 dwarf_dealloc(dbg,name,DW_DLA_STRING);
719 pubtypes.push_back(p);
720 }
721 }
722 dwarf_types_dealloc(dbg, types, cnt);
723 } else if (res == DW_DLV_ERROR) {
724 cerr << "dwarf_get_globals failed" << endl;
725 exit(1);
726 }
727
728
729
730
731 }
732
733