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 &macrodata = 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(&macrooffset,&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