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