1 /*
2   Copyright (C) 2010-2016 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 // dwarfgen.cc
28 //
29 // Using some information source, create a tree of dwarf
30 // information (speaking of a DIE tree).
31 // Turn the die tree into dwarfdata using libdwarf producer
32 // and write the resulting data in an object file.
33 // It is a bit inconsistent in error handling just to
34 // demonstrate the various possibilities using the producer
35 // library.
36 //
37 //  dwarfgen [-t def|obj|txt] [-o outpath] [-c cunum]  path
38 
39 //  where -t means what sort of input to read
40 //         def means predefined (no input is read, the output
41 //         is based on some canned setups built into dwarfgen).
42 //         'path' is ignored in this case. This is the default.
43 //
44 //         obj means 'path' is required, it is the object file to
45 //             read (the dwarf sections are duplicated in the output file)
46 //
47 //         txt means 'path' is required, path must contain plain text
48 //             (in a form rather like output by dwarfdump)
49 //             that defines the dwarf that is to be output.
50 //
51 //  where  -o means specify the pathname of the output object. If not
52 //         supplied testout.o is used as the default output path.
53 //  where -c supplies a CU number of the obj input to output
54 //         because the dwarf producer wants just one CU.
55 //         Default is -1 which won't match anything.
56 
57 #include "config.h"
58 
59 /* Windows specific header files */
60 #ifdef HAVE_STDAFX_H
61 #include "stdafx.h"
62 #endif /* HAVE_STDAFX_H */
63 
64 #include <unistd.h>
65 #include <stdlib.h> // for exit
66 #include <iostream>
67 #include <sstream>
68 #include <iomanip>
69 #include <string>
70 #include <list>
71 #include <map>
72 #include <vector>
73 #include <string.h> // For memset etc
74 #include <sys/stat.h> //open
75 #include <fcntl.h> //open
76 #include "general.h"
77 #include "dwgetopt.h"
78 #include "gelf.h"
79 #include "strtabdata.h"
80 #include "dwarf.h"
81 #include "libdwarf.h"
82 #include "irepresentation.h"
83 #include "ireptodbg.h"
84 #include "createirepfrombinary.h"
85 
86 using std::string;
87 using std::cout;
88 using std::cerr;
89 using std::endl;
90 using std::vector;
91 
92 static void write_object_file(Dwarf_P_Debug dbg, IRepresentation &irep);
93 static void write_text_section(Elf * elf);
94 static void write_generated_dbg(Dwarf_P_Debug dbg,Elf * elf,
95     IRepresentation &irep);
96 
97 static string outfile("testout.o");
98 static string infile;
99 static enum  WhichInputSource { OptNone, OptReadText,OptReadBin,OptPredefined}
100     whichinput(OptPredefined);
101 
102 /*  Use a generic call to open the file, due to issues with Windows */
103 int open_a_file(const char * name);
104 int create_a_file(const char * name);
105 void close_a_file(int f);
106 
107 // This is a global so thet CallbackFunc can get to it
108 // If we used the dwarf_producer_init_c() user_data pointer
109 // creatively we would not need a global.
110 static IRepresentation Irep;
111 
112 static Elf * elf = 0;
113 static Elf32_Ehdr * ehp = 0;
114 static strtabdata secstrtab;
115 
116 bool transformHighpcToConst = false;
117 int  defaultInfoStringForm = DW_FORM_string;
118 bool showrelocdetails = false;
119 
120 // loff_t is signed for some reason (strange) but we make offsets unsigned.
121 #define LOFFTODWUNS(x)  ( (Dwarf_Unsigned)(x))
122 
123 /*  See the Elf ABI for further definitions of these fields. */
124 class SectionFromDwarf {
125 public:
126     std::string name_;
127     Dwarf_Unsigned section_name_itself_;
128     ElfSymIndex section_name_symidx_;
129     int size_;
130     Dwarf_Unsigned type_;
131     Dwarf_Unsigned flags_;
132 
133     /*  type: SHT_REL, RELA: Section header index of the section
134         relocation applies to.
135         SHT_SYMTAB: Section header index of the associated string table. */
136     Dwarf_Unsigned link_;
137 
138     /*  type: SHT_REL, RELA: Section header index of the section
139         relocation applies to.
140         SHT_SYMTAB: One greater than index of the last local symbol.. */
141     Dwarf_Unsigned info_;
142 private:
143     ElfSectIndex elf_sect_index_;
144     Dwarf_Unsigned lengthWrittenToElf_;
145 public:
getNextOffset()146     Dwarf_Unsigned getNextOffset() { return lengthWrittenToElf_; }
setNextOffset(Dwarf_Unsigned v)147     void setNextOffset(Dwarf_Unsigned v) { lengthWrittenToElf_ = v; }
148 
getSectionNameSymidx()149     unsigned getSectionNameSymidx() {
150         return section_name_symidx_.getSymIndex(); };
SectionFromDwarf()151     SectionFromDwarf():section_name_itself_(0),
152         section_name_symidx_(0),
153         size_(0),type_(0),flags_(0),
154         link_(0), info_(0), elf_sect_index_(0),
155         lengthWrittenToElf_(0) {} ;
~SectionFromDwarf()156     ~SectionFromDwarf() {};
setSectIndex(ElfSectIndex v)157     void setSectIndex(ElfSectIndex v) { elf_sect_index_ = v;}
getSectIndex() const158     ElfSectIndex getSectIndex() const { return elf_sect_index_;}
SectionFromDwarf(const std::string & name,int size,Dwarf_Unsigned type,Dwarf_Unsigned flags,Dwarf_Unsigned link,Dwarf_Unsigned info)159     SectionFromDwarf(const std::string&name,
160         int size,Dwarf_Unsigned type,Dwarf_Unsigned flags,
161         Dwarf_Unsigned link, Dwarf_Unsigned info):
162         name_(name),
163         size_(size),type_(type),flags_(flags),
164         link_(link), info_(info), elf_sect_index_(0),
165         lengthWrittenToElf_(0) {
166             // Now create section name string section.
167             section_name_itself_ = secstrtab.addString(name.c_str());
168             ElfSymbols& es = Irep.getElfSymbols();
169             // Now creat a symbol for the section name.
170             // (which has its own string table)
171             section_name_symidx_  = es.addElfSymbol(0,name);
172     } ;
173 };
174 
175 vector<SectionFromDwarf> dwsectab;
176 
177 static ElfSectIndex create_dw_elf(SectionFromDwarf  &ds);
178 
FindMySection(const ElfSectIndex & elf_section_index)179 static SectionFromDwarf & FindMySection(const ElfSectIndex & elf_section_index)
180 {
181     for(unsigned i =0; i < dwsectab.size(); ++i) {
182         if(elf_section_index.getSectIndex() !=
183             dwsectab[i].getSectIndex().getSectIndex()) {
184             continue;
185         }
186         return dwsectab[i];
187     }
188     cerr << "dwarfgen: Unable to find my dw sec data for elf section " <<
189         elf_section_index.getSectIndex() << endl;
190     exit(1);
191 }
192 
FindMySectionNum(const ElfSectIndex & elf_section_index)193 static int FindMySectionNum(const ElfSectIndex & elf_section_index)
194 {
195     for(unsigned i =0; i < dwsectab.size(); ++i) {
196         if(elf_section_index.getSectIndex() !=
197             dwsectab[i].getSectIndex().getSectIndex()) {
198             continue;
199         }
200         return i;
201     }
202     cerr << "dwarfgen: Unable to find my dw sec index for elf section " <<
203         elf_section_index.getSectIndex() << endl;
204     exit(1);
205 }
206 
207 static unsigned
createnamestr(unsigned strtabstroff)208 createnamestr(unsigned strtabstroff)
209 {
210     Elf_Scn * strscn =elf_newscn(elf);
211     if(!strscn) {
212         cerr << "dwarfgen: Unable to elf_newscn() on " << outfile << endl;
213         exit(1);
214     }
215     Elf_Data* shstr =elf_newdata(strscn);
216     if(!shstr) {
217         cerr << "dwarfgen: Unable to elf_newdata() on " << outfile << endl;
218         exit(1);
219     }
220     shstr->d_buf = secstrtab.exposedata();
221     shstr->d_type =  ELF_T_BYTE;
222     shstr->d_size = secstrtab.exposelen();
223     shstr->d_off = 0;
224     shstr->d_align = 1;
225     shstr->d_version = EV_CURRENT;
226 
227     Elf32_Shdr * strshdr = elf32_getshdr(strscn);
228     if(!strshdr) {
229         cerr << "dwarfgen: Unable to elf_getshdr() on " << outfile << endl;
230         exit(1);
231     }
232     strshdr->sh_name =  strtabstroff;
233     strshdr->sh_type= SHT_STRTAB;
234     strshdr->sh_flags = SHF_STRINGS;
235     strshdr->sh_addr = 0;
236     strshdr->sh_offset = 0;
237     strshdr->sh_size = 0;
238     strshdr->sh_link  = 0;
239     strshdr->sh_info = 0;
240     strshdr->sh_addralign = 1;
241     strshdr->sh_entsize = 0;
242     return  elf_ndxscn(strscn);
243 }
244 
245 // This functional interface is defined by libdwarf.
246 // Please see the comments in libdwarf2p.1.pdf
247 // (libdwarf2p.1.mm)  on this callback interface.
248 // Returns (to libdwarf) an Elf section number, so
249 // since 0 is always empty and dwarfgen sets 1 to be a fake
250 // text section on the first call this returns 2, second 3, etc.
CallbackFunc(const char * name,int size,Dwarf_Unsigned type,Dwarf_Unsigned flags,Dwarf_Unsigned link,Dwarf_Unsigned info,Dwarf_Unsigned * sect_name_symbol_index,void * user_data,int * error)251 int CallbackFunc(
252     const char* name,
253     int                 size,
254     Dwarf_Unsigned      type,
255     Dwarf_Unsigned      flags,
256     Dwarf_Unsigned      link,
257     Dwarf_Unsigned      info,
258     Dwarf_Unsigned*     sect_name_symbol_index,
259     void *              user_data,
260     int*                error)
261 {
262     // Create an elf section.
263     // If the data is relocations, we suppress the generation
264     // of a section when we intend to do the relocations
265     // ourself (fine for dwarfgen but would
266     // be really surprising for a normal compiler
267     // back end using the producer code).
268 
269     // The section name appears both in the section strings
270     // .shstrtab and
271     // in the elf symtab .symtab and its strings .strtab.
272 
273     if (0 == strncmp(name,".rel",4))  {
274         // It is relocation, create no section!
275         return 0;
276     }
277     SectionFromDwarf ds(name,size,type,flags,link,info) ;
278 
279     // It is up to you to provide (to libdwarf,
280     // to generate relocation records)
281     // a symbol index for the section.
282     // In Elf, each section gets an elf symbol table entry.
283     // So that relocations have an address to refer to.
284     // You will create the Elf symbol table, so you have to tell
285     // libdwarf the index to put into relocation records for the
286     // section newly defined here.
287     *sect_name_symbol_index = ds.getSectionNameSymidx();
288     ElfSectIndex createdsec = create_dw_elf(ds);
289 
290     // Do all the data creation before pushing
291     // (copying) ds onto dwsectab!
292     dwsectab.push_back(ds);
293     // The number returned is elf section, not dwsectab[] index
294     return createdsec.getSectIndex();
295 }
296 
297 // Here we create a new Elf section
298 // This never happens for relocations in dwarfgen,
299 // only a few sections are created by dwarfgen.
300 static ElfSectIndex
create_dw_elf(SectionFromDwarf & ds)301 create_dw_elf(SectionFromDwarf  &ds)
302 {
303     Elf_Scn * scn =elf_newscn(elf);
304     if(!scn) {
305         cerr << "dwarfgen: Unable to elf_newscn() on " << ds.name_  << endl;
306         exit(1);
307     }
308     Elf32_Shdr * shdr = elf32_getshdr(scn);
309     if(!shdr) {
310         cerr << "dwarfgen: Unable to elf_getshdr() on " << ds.name_ << endl;
311         exit(1);
312     }
313     shdr->sh_name   = ds.section_name_itself_;
314     shdr->sh_type   = ds.type_;
315     shdr->sh_flags  = ds.flags_;
316     shdr->sh_addr   = 0;
317     shdr->sh_offset = 0;
318     shdr->sh_size   = ds.size_;
319     shdr->sh_link   = ds.link_;
320     shdr->sh_info   = ds.info_;
321     shdr->sh_addralign = 1;
322     shdr->sh_entsize = 0;
323     ElfSectIndex si(elf_ndxscn(scn));
324 
325     ds.setSectIndex(si);
326     cout << "New Elf section: "<< ds.name_ <<
327         " Type="<< ds.type_ <<
328         " Flags="<< ds.flags_ <<
329         " Elf secnum="<< si.getSectIndex() <<
330         " link section=" << ds.link_<<
331         " info=" << ds.info_ << endl ;
332     return  si;
333 }
334 
335 // Default error handler of libdwarf producer code.
ErrorHandler(Dwarf_Error err,Dwarf_Ptr errarg)336 void ErrorHandler(Dwarf_Error err,Dwarf_Ptr errarg)
337 {
338     // FIXME do better error handling
339     cerr <<"dwarfgen: Giving up, encountered an error" << endl;
340     exit(1);
341 }
342 
343 
344 static void
setinput(enum WhichInputSource * src,const string & type,bool * pathreq)345 setinput(enum  WhichInputSource *src,
346     const string &type,
347     bool *pathreq)
348 {
349     if(type == "txt") {
350         *src = OptReadText;
351         *pathreq = true;
352         return;
353     } else if (type == "obj") {
354         *src = OptReadBin;
355         *pathreq = true;
356         return;
357     } else if (type == "def") {
358         *src = OptPredefined;
359         *pathreq = false;
360         return;
361     }
362     cout << "dwarfgen: Giving up, only txt obj or def accepted after -t" << endl;
363     exit(1);
364 }
365 
366 int
main(int argc,char ** argv)367 main(int argc, char **argv)
368 {
369     try {
370         int opt;
371         bool pathrequired(false);
372         long cu_of_input_we_output = -1;
373         while((opt=dwgetopt(argc,argv,"o:t:c:hsr")) != -1) {
374             switch(opt) {
375             case 'c':
376                 // At present we can only create a single
377                 // cu in the output of the libdwarf producer.
378                 cu_of_input_we_output = atoi(dwoptarg);
379                 break;
380             case 'r':
381                 showrelocdetails=true;
382                 break;
383             case 's':
384                 defaultInfoStringForm = DW_FORM_strp;
385                 break;
386             case 't':
387                 setinput(&whichinput,dwoptarg,&pathrequired);
388                 break;
389             case 'h':
390                 transformHighpcToConst = true;
391                 break;
392             case 'o':
393                 outfile = dwoptarg;
394                 break;
395             case '?':
396                 cerr << "dwarfgen: Invalid quest? option input " << endl;
397                 exit(1);
398             default:
399                 cerr << "dwarfgen: Invalid option input " << endl;
400                 exit(1);
401             }
402         }
403         if ( (dwoptind >= argc) && pathrequired) {
404             cerr << "dwarfgen: Expected argument after options! Giving up."
405                 << endl;
406             exit(EXIT_FAILURE);
407         }
408         if(pathrequired) {
409             infile = argv[dwoptind];
410         }
411 
412         if(whichinput == OptReadBin) {
413             createIrepFromBinary(infile,Irep);
414         } else if (whichinput == OptReadText) {
415             cerr << "dwarfgen: dwarfgen: text read not supported yet" << endl;
416             exit(EXIT_FAILURE);
417         } else if (whichinput == OptPredefined) {
418             cerr << "dwarfgen: predefined not supported yet" << endl;
419             exit(EXIT_FAILURE);
420         } else {
421             cerr << "dwarfgen: Impossible: unknown input style." << endl;
422             exit(EXIT_FAILURE);
423         }
424         // Example will return error value thru 'err' pointer
425         // and return DW_DLV_BADADDR if there is an error.
426         int ptrsizeflagbit = DW_DLC_POINTER32;
427         int offsetsizeflagbit = DW_DLC_OFFSET32;
428         const char * isa_name = "x86";
429         const char *dwarf_version = "V2";
430         int endian =  DW_DLC_TARGET_LITTLEENDIAN;
431         Dwarf_Ptr errarg = 0;
432         Dwarf_Error err = 0;
433         void *user_data = 0;
434         Dwarf_P_Debug dbg = 0;
435         // We use DW_DLC_SYMBOLIC_RELOCATIONS so we can
436         // read the relocations and do our own relocating.
437         // See calls of dwarf_get_relocation_info().
438         int res = dwarf_producer_init(
439             DW_DLC_WRITE|ptrsizeflagbit|
440             offsetsizeflagbit|DW_DLC_SYMBOLIC_RELOCATIONS|
441             endian,
442             CallbackFunc,
443             0, // errhand
444             errarg,
445             user_data,
446             isa_name,
447             dwarf_version,
448             0, // No extra identifying strings.
449             &dbg,
450             &err);
451         if(res != DW_DLV_OK) {
452             cerr << "dwarfgen: Failed init_b" << endl;
453             exit(EXIT_FAILURE);
454         }
455         res = dwarf_pro_set_default_string_form(dbg,
456             defaultInfoStringForm,&err);
457         if(res != DW_DLV_OK) {
458             cerr << "dwarfgen: Failed dwarf_pro_set_default_string_form"
459                 << endl;
460             exit(EXIT_FAILURE);
461         }
462         transform_irep_to_dbg(dbg,Irep,cu_of_input_we_output);
463         write_object_file(dbg,Irep);
464         // Example calls ErrorHandler if there is an error
465         // (which does not return, see above)
466         // so no need to test for error.
467         Dwarf_Unsigned str_count = 0;
468         Dwarf_Unsigned str_len = 0;
469         Dwarf_Unsigned debug_str_count = 0;
470         Dwarf_Unsigned debug_str_len = 0;
471         Dwarf_Unsigned reused_count = 0;
472         Dwarf_Unsigned reused_len = 0;
473         res = dwarf_pro_get_string_stats(dbg,
474             &str_count,&str_len,
475             &debug_str_count,
476             &debug_str_len,
477             &reused_count,
478             &reused_len,&err);
479         cout << "Debug_Str: debug_info str count " <<str_count <<
480             ", byte total len " <<str_len << endl;
481         cout << "Debug_Str: count " <<debug_str_count <<
482             ", byte total len " <<debug_str_len << endl;
483         cout << "Debug_Str: Reused count " <<reused_count <<
484             ", byte total len not emitted " <<reused_len << endl;
485         dwarf_producer_finish( dbg, 0);
486         return 0;
487     } // End try
488     catch (std::bad_alloc &ba) {
489         cout << "dwarfgen FAIL:bad alloc caught " << ba.what() << endl;
490         exit(EXIT_FAILURE);
491     }
492     catch (std::exception &e) {
493         cout << "dwarfgen FAIL:std lib exception " << e.what() << endl;
494         exit(EXIT_FAILURE);
495     }
496     catch (...) {
497         cout << "dwarfgen FAIL:other failure " << endl;
498         exit(EXIT_FAILURE);
499     }
500     exit(1);
501 }
502 
503 static void
write_object_file(Dwarf_P_Debug dbg,IRepresentation & irep)504 write_object_file(Dwarf_P_Debug dbg, IRepresentation &irep)
505 {
506     int fd = create_a_file(outfile.c_str());
507     if(fd < 0 ) {
508         cerr << "dwarfgen: Unable to open " << outfile <<
509             " for writing." << endl;
510         exit(1);
511     }
512 
513     if(elf_version(EV_CURRENT) == EV_NONE) {
514         cerr << "dwarfgen: Bad elf_version" << endl;
515         exit(1);
516     }
517 
518     Elf_Cmd cmd = ELF_C_WRITE;
519     elf = elf_begin(fd,cmd,0);
520     if(!elf) {
521         cerr << "dwarfgen: Unable to elf_begin() on " << outfile << endl;
522         exit(1);
523     }
524     ehp = elf32_newehdr(elf);
525     if(!ehp) {
526         cerr << "dwarfgen: Unable to elf_newehdr() on " << outfile << endl;
527         exit(1);
528     }
529     ehp->e_ident[EI_MAG0] = ELFMAG0;
530     ehp->e_ident[EI_MAG1] = ELFMAG1;
531     ehp->e_ident[EI_MAG2] = ELFMAG2;
532     ehp->e_ident[EI_MAG3] = ELFMAG3;
533     ehp->e_ident[EI_CLASS] = ELFCLASS32;
534     ehp->e_ident[EI_DATA] = ELFDATA2LSB;
535     ehp->e_ident[EI_VERSION] = EV_CURRENT;
536     ehp->e_machine = EM_386;
537     //  We do not bother to create program headers, so
538     //  mark this as ET_REL.
539     ehp->e_type = ET_REL;
540     ehp->e_version = EV_CURRENT;
541 
542     unsigned  strtabstroff = secstrtab.addString(".shstrtab");
543 
544     // an object section with fake .text data (just as an example).
545     write_text_section(elf);
546 
547     write_generated_dbg(dbg,elf,Irep);
548 
549     // Now create section name string section.
550     unsigned shstrindex = createnamestr(strtabstroff);
551     ehp->e_shstrndx = shstrindex;
552 
553     off_t ures = elf_update(elf,cmd);
554     if(ures == (off_t)(-1LL)) {
555         cerr << "dwarfgen: Unable to elf_update() on " << outfile << endl;
556         int eer = elf_errno();
557         cerr << "Error is " << eer << " " << elf_errmsg(eer) << endl;
558         exit(1);
559     }
560     cout << " output image size in bytes " << ures << endl;
561 
562     elf_end(elf);
563     close_a_file(fd);
564 }
565 
566 
567 // an object section with fake .text data (just as an example).
568 static void
write_text_section(Elf * elf)569 write_text_section(Elf * elf)
570 {
571     unsigned  osecnameoff = secstrtab.addString(".text");
572     Elf_Scn * scn1 =elf_newscn(elf);
573     if(!scn1) {
574         cerr << "dwarfgen: Unable to elf_newscn() on " << outfile << endl;
575         exit(1);
576     }
577 
578     Elf_Data* ed1 =elf_newdata(scn1);
579     if(!ed1) {
580         cerr << "dwarfgen: Unable to elf_newdata() on " << outfile << endl;
581         exit(1);
582     }
583     const char *d = "data in section";
584     ed1->d_buf = (void *)d;
585     ed1->d_type =  ELF_T_BYTE;
586     ed1->d_size = strlen(d) +1;
587     ed1->d_off = 0;
588     ed1->d_align = 4;
589     ed1->d_version = EV_CURRENT;
590     Elf32_Shdr * shdr1 = elf32_getshdr(scn1);
591     if(!shdr1) {
592         cerr << "dwarfgen: Unable to elf_getshdr() on " << outfile << endl;
593         exit(1);
594     }
595     shdr1->sh_name =  osecnameoff;
596     shdr1->sh_type= SHT_PROGBITS;
597     shdr1->sh_flags = 0;
598     shdr1->sh_addr = 0;
599     shdr1->sh_offset = 0;
600     shdr1->sh_size = 0;
601     shdr1->sh_link  = 0;
602     shdr1->sh_info = 0;
603     shdr1->sh_addralign = 1;
604     shdr1->sh_entsize = 0;
605 }
606 static void
InsertDataIntoElf(Dwarf_Signed d,Dwarf_P_Debug dbg,Elf * elf)607 InsertDataIntoElf(Dwarf_Signed d,Dwarf_P_Debug dbg,Elf *elf)
608 {
609     Dwarf_Signed elf_section_index = 0;
610     Dwarf_Unsigned length = 0;
611     Dwarf_Ptr bytes = dwarf_get_section_bytes(dbg,d,
612         &elf_section_index,&length,0);
613 
614     Elf_Scn *scn =  elf_getscn(elf,elf_section_index);
615     if(!scn) {
616         cerr << "dwarfgen: Unable to elf_getscn on disk transform # " << d << endl;
617         exit(1);
618     }
619 
620     ElfSectIndex si(elf_section_index);
621     SectionFromDwarf & sfd  = FindMySection(si);
622 
623     Elf_Data* ed =elf_newdata(scn);
624     if(!ed) {
625         cerr << "dwarfgen: elf_newdata died on transformed index " << d << endl;
626         exit(1);
627     }
628     ed->d_buf = bytes;
629     ed->d_type =  ELF_T_BYTE;
630     ed->d_size = length;
631     ed->d_off = sfd.getNextOffset();
632     sfd.setNextOffset(ed->d_off + length);
633     ed->d_align = 1;
634     ed->d_version = EV_CURRENT;
635     cout << "Inserted " << length << " bytes into elf section index " <<
636         elf_section_index << endl;
637 }
638 
639 #if 0
640 static string
641 printable_rel_type(unsigned char reltype)
642 {
643     enum Dwarf_Rel_Type t = (enum Dwarf_Rel_Type)reltype;
644     switch(t) {
645     case   dwarf_drt_none:
646         return "dwarf_drt_none";
647     case   dwarf_drt_data_reloc:
648         return "dwarf_drt_data_reloc";
649     case   dwarf_drt_segment_rel:
650         return "dwarf_drt_segment_rel";
651     case   dwarf_drt_first_of_length_pair:
652         return "dwarf_drt_first_of_length_pair";
653     case   dwarf_drt_second_of_length_pair:
654         return "dwarf_drt_second_of_length_pair";
655     default:
656         break;
657     }
658     return "drt-unknown (impossible case)";
659 }
660 #endif
661 
662 static Dwarf_Unsigned
FindSymbolValue(ElfSymIndex symi,IRepresentation & irep)663 FindSymbolValue(ElfSymIndex symi,IRepresentation &irep)
664 {
665     ElfSymbols & syms = irep.getElfSymbols();
666     ElfSymbol & es =  syms.getElfSymbol(symi);
667     Dwarf_Unsigned symv = es.getSymbolValue();
668     return symv;
669 }
670 
671 static void
bitreplace(char * buf,Dwarf_Unsigned newval,size_t newvalsize,int length)672 bitreplace(char *buf, Dwarf_Unsigned newval,
673     size_t newvalsize,int length)
674 {
675     if(length == 4) {
676         uint32_t my4 = newval;
677         uint32_t * p = reinterpret_cast<uint32_t *>(buf );
678         uint32_t oldval = *p;
679         *p = oldval + my4;
680     } else if (length == 8) {
681         uint64_t my8 = newval;
682         uint64_t * p = reinterpret_cast<uint64_t *>(buf );
683         uint64_t oldval = *p;
684         *p = oldval + my8;
685     } else {
686         cerr << "dwarfgen:  Relocation is length " << length <<
687             " which we do not yet handle." << endl;
688         exit(1);
689     }
690 }
691 
692 // This remembers nothing, so is dreadfully slow.
693 static char *
findelfbuf(Elf * elf,Elf_Scn * scn,Dwarf_Unsigned offset,unsigned length)694 findelfbuf(Elf *elf,Elf_Scn *scn,Dwarf_Unsigned offset, unsigned length)
695 {
696     Elf_Data * edbase = 0;
697     Elf_Data * ed = elf_getdata(scn,edbase);
698     unsigned bct = 0;
699     for (;ed; ed = elf_getdata(scn,ed)) {
700         bct++;
701         if(offset >= LOFFTODWUNS(ed->d_off + ed->d_size) ) {
702             continue;
703         }
704         if(offset < LOFFTODWUNS(ed->d_off)) {
705             cerr << "dwarfgen:  Relocation at offset  " <<
706                 offset << " cannot be accomplished, no buffer. "
707                 << endl;
708             exit(1);
709         }
710         Dwarf_Unsigned localoff = offset - ed->d_off;
711         if((localoff + length) > ed->d_size) {
712             cerr << "dwarfgen:  Relocation at offset  " <<
713                 offset << " cannot be accomplished, size mismatch. "
714                 << endl;
715             exit(1);
716         }
717         char *lclptr = reinterpret_cast<char *>(ed->d_buf) + localoff;
718         return lclptr;
719     }
720     cerr << " Relocation at offset  " << offset  <<
721         " cannot be accomplished,  past end of buffers" << endl;
722     return 0;
723 
724 }
725 
726 static void
write_generated_dbg(Dwarf_P_Debug dbg,Elf * elf,IRepresentation & irep)727 write_generated_dbg(Dwarf_P_Debug dbg,Elf * elf,IRepresentation &irep)
728 {
729     Dwarf_Error err = 0;
730     Dwarf_Signed sectioncount =
731         dwarf_transform_to_disk_form(dbg,0);
732 
733     Dwarf_Signed d = 0;
734     for(d = 0; d < sectioncount ; ++d) {
735         InsertDataIntoElf(d,dbg,elf);
736     }
737 
738     // Since we are emitting in final form sometimes, we may
739     // do relocation processing here or we could (but do not)
740     // emit relocation records into the object file.
741     // The following is for DW_DLC_SYMBOLIC_RELOCATIONS.
742 
743     Dwarf_Unsigned reloc_sections_count = 0;
744     int drd_version = 0;
745     int res = dwarf_get_relocation_info_count(dbg,&reloc_sections_count,
746         &drd_version,&err);
747     if( res != DW_DLV_OK) {
748         cerr << "dwarfgen: Error getting relocation info count." << endl;
749         exit(1);
750 
751     }
752     cout << "Relocations sections count= " << reloc_sections_count <<
753         " relversion=" << drd_version << endl;
754     for( Dwarf_Unsigned ct = 0; ct < reloc_sections_count ; ++ct) {
755         // elf_section_index is the elf index of the
756         // section to be relocated, and the section number
757         // in the object file which we are creating.
758         // In dwarfgen we do not use this as we do not create
759         // relocation sections. Here it is always zero.
760         Dwarf_Signed elf_section_index = 0;
761 
762         // elf_section_index_link is the elf index of the
763         // section  the relocations apply to, such as .debug_info.
764         // An elf index, not dwsectab[] index.
765         Dwarf_Signed elf_section_index_link = 0;
766 
767         // relocation_buffer_count is the number of relocations
768         // of this section.
769         Dwarf_Unsigned relocation_buffer_count = 0;
770         Dwarf_Relocation_Data reld;
771         res = dwarf_get_relocation_info(dbg,&elf_section_index,
772             &elf_section_index_link,
773             &relocation_buffer_count,
774             &reld,&err);
775         // elf_section_index_link
776         // refers to the output section numbers, not to dwsectab.
777         if (res != DW_DLV_OK) {
778             cerr << "dwarfgen: Error getting relocation record " <<
779                 ct << "."  << endl;
780             exit(1);
781         }
782 
783         int dwseclink =  FindMySectionNum(elf_section_index_link);
784         ElfSectIndex sitarg = dwsectab[dwseclink].getSectIndex();
785         string linktarg= dwsectab[dwseclink].name_;
786         long int targsec = sitarg.getSectIndex();
787 
788         cout << "Relocs for sec=" << ct <<
789             " ourlinkto="       << elf_section_index_link <<
790             " linktoobjsecnum=" << targsec <<
791             " name="            << linktarg <<
792             " reloc-count="     << relocation_buffer_count << endl;
793         Elf_Scn *scn =  elf_getscn(elf,elf_section_index_link);
794         if(!scn) {
795             cerr << "dwarfgen: Unable to elf_getscn  # " <<
796                 elf_section_index_link << endl;
797             exit(1);
798         }
799 
800         for (Dwarf_Unsigned r = 0; r < relocation_buffer_count; ++r) {
801             Dwarf_Relocation_Data rec = reld+r;
802             ElfSymIndex symi(rec->drd_symbol_index);
803             Dwarf_Unsigned newval = FindSymbolValue(symi,irep);
804             char *buf_to_update = findelfbuf(elf,scn,
805                 rec->drd_offset,rec->drd_length);
806 
807             if(buf_to_update) {
808                 if(showrelocdetails) {
809                     cout << "Reloc "<< r <<
810                         " symindex=" << rec->drd_symbol_index <<
811                         " targoffset= " << IToHex(rec->drd_offset) <<
812                         " newval = " << IToHex(newval) << endl;
813                 }
814                 bitreplace(buf_to_update, newval,sizeof(newval),
815                     rec->drd_length);
816             } else {
817                 if(showrelocdetails) {
818                     cout << "Reloc "<< r << "does nothing"<<endl;
819                 }
820             }
821         }
822     }
823 }
824 
825 int
open_a_file(const char * name)826 open_a_file(const char * name)
827 {
828     /* Set to a file number that cannot be legal. */
829     int f = -1;
830 
831 #if defined(__CYGWIN__) || defined(_WIN32)
832     /*  It is not possible to share file handles
833         between applications or DLLs. Each application has its own
834         file-handle table. For two applications to use the same file
835         using a DLL, they must both open the file individually.
836         Let the 'libelf' dll to open and close the file.  */
837 
838     /* For WIN32 open the file as binary */
839     f = elf_open(name, O_RDONLY | O_BINARY);
840 #else
841     f = open(name, O_RDONLY);
842 #endif
843     return f;
844 }
845 
846 int
create_a_file(const char * name)847 create_a_file(const char * name)
848 {
849     /* Set to a file number that cannot be legal. */
850     int f = -1;
851 
852 #if defined(__CYGWIN__) || defined(_WIN32)
853     /*  It is not possible to share file handles
854         between applications or DLLs. Each application has its own
855         file-handle table. For two applications to use the same file
856         using a DLL, they must both open the file individually.
857         Let the 'libelf' dll to open and close the file.  */
858 
859     /* For WIN32 create the file as binary */
860     f = elf_open(name, O_WRONLY | O_CREAT | O_BINARY);
861 #else
862     int mode =  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
863     f = open(name,O_WRONLY | O_CREAT | O_TRUNC, mode);
864 #endif
865     return f;
866 }
867 
868 void
close_a_file(int f)869 close_a_file(int f)
870 {
871     close(f);
872 }
873