Redid static ctor/dtor handling to be compatible with init_array/fini_array as well...
[dyninst.git] / symtabAPI / src / emitElfStatic-x86.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 /* 
32  * holds architecture specific functions for x86 and x86_64 architecture needed for the
33  * static executable rewriter
34  */
35
36 #include <cstdlib>
37 #include <cstdio>
38 #include <cassert>
39 #include <iostream>
40 #include <set>
41 #include <map>
42 #include <sstream>
43
44 #include "emitElfStatic.h"
45 #include "Symtab.h"
46 #include "Symbol.h"
47 #include "Archive.h"
48 #include "Object.h"
49 #include "Region.h"
50 #include "debug.h"
51
52 using namespace Dyninst;
53 using namespace Dyninst::SymtabAPI;
54
55 static const Offset GOT_RESERVED_SLOTS = 3;
56 static const unsigned X86_WIDTH = 4;
57 static const unsigned X86_64_WIDTH = 8;
58
59 #if defined(os_freebsd)
60 #define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT
61 #endif
62
63 // Used in an assert so needs to be a macro
64 #define UNKNOWN_ADDRESS_WIDTH_ASSERT "An unknown address width was encountered, can't continue"
65
66 /* NOTE:
67  * As most of these functions are defined per architecture, the description of
68  * each of these functions is in the emitElfStatic header. Comments describing
69  * the function interface are explicitly left out.
70  */
71
72 /**
73  * Specific to x86
74  *
75  * Given a relocation, determines if the relocation corresponds to a .ctors or .dtors
76  * table that requires special consideration. Modifies the passed symbol offset to
77  * point to the right table, if applicable.
78  *
79  * rel          The relocation entry to examine
80  * globalOffset The offset of the linked code (used for symbol offset calculation)
81  * lmap         Holds information about .ctors/.dtors tables
82  * errMsg       Set on error
83  * symbolOffset Modified by this routine to contain the offset of the table
84  *
85  * Returns true, if there are no errors including the case where the relocation 
86  * entry doesn't reference the .ctors/.dtors tables.
87  */
88 static bool computeCtorDtorAddress(relocationEntry &rel, Offset globalOffset,
89         LinkMap &lmap, string &errMsg, Offset &symbolOffset)
90 {
91   /*
92     if( rel.name() ==  SYMTAB_CTOR_LIST_REL ) {
93         // This needs to be: (the location of the .ctors table)
94         if( lmap.newCtorRegions.size() > 0 ) {
95             symbolOffset = lmap.ctorRegionOffset + globalOffset;
96         }else if( lmap.originalCtorRegion != NULL ) {
97             symbolOffset = lmap.originalCtorRegion->getDiskOffset();
98         }else{
99             errMsg = "Failed to locate original .ctors Region -- cannot apply relocation";
100             return false;
101         }
102     }else if( rel.name() == SYMTAB_DTOR_LIST_REL ) {
103         // This needs to be: (the location of the .dtors table)
104         if( lmap.newDtorRegions.size() > 0 ) {
105             symbolOffset = lmap.dtorRegionOffset + globalOffset;
106         }else if( lmap.originalDtorRegion != NULL ) {
107             symbolOffset = lmap.originalDtorRegion->getDiskOffset();
108         }else{
109             errMsg = "Failed to locate original .dtors Region -- cannot apply relocation";
110             return false;
111         }
112         } else*/
113     if (rel.name() == SYMTAB_IREL_START) {
114       // Start of our moved relocation section
115       symbolOffset = globalOffset + lmap.relRegionOffset;
116     }
117     else if (rel.name() == SYMTAB_IREL_END) {
118       // End of our moved relocation section
119       symbolOffset = globalOffset + lmap.relRegionOffset + lmap.relSize;
120     }
121
122     return true;
123 }
124
125 bool emitElfStatic::archSpecificRelocation(Symtab *, Symtab *, char *targetData, relocationEntry &rel,
126        Offset dest, Offset relOffset, Offset globalOffset, LinkMap &lmap,
127        string &errMsg) 
128 {
129   Offset symbolOffset = 0;
130   if (rel.getDynSym()->getType() != Symbol::ST_INDIRECT) {
131     // Easy case, just use the symbol as given
132     symbolOffset = rel.getDynSym()->getOffset();
133   }
134   else {
135     // Indirect; the address is the PLT entry (yes, I said PLT)
136     // associated with this symbol. 
137     auto pltEntry = lmap.pltEntries.find(rel.getDynSym()); 
138     if (pltEntry == lmap.pltEntries.end()) {
139       return false;
140     }
141     symbolOffset = pltEntry->second.first + globalOffset;
142   }
143     
144     if( X86_WIDTH == addressWidth_ ) {
145         /*
146          * Referring to the SYSV 386 supplement:
147          *
148          * All relocations on x86 are one word32 == Elf32_Word
149          *
150          * S = symbolOffset
151          * A = addend
152          * P = relOffset
153          */
154        
155         Elf32_Word addend;
156         if( rel.regionType() == Region::RT_REL ) {
157             memcpy(&addend, &targetData[dest], sizeof(Elf32_Word));
158         }else if( rel.regionType() == Region::RT_RELA ) {
159             addend = rel.addend();
160         }
161
162         if( !computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset) ) {
163             return false;
164         }
165
166         rewrite_printf("relocation for '%s': TYPE = %s(%lu) S = %lx A = %lx P = %lx\n",
167                 rel.name().c_str(), 
168                 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
169                 rel.getRelType(), symbolOffset, addend, relOffset);
170
171         Offset relocation = 0;
172         map<Symbol *, Offset>::iterator result;
173         stringstream tmp;
174
175         switch(rel.getRelType()) {
176             case R_386_32:
177                 relocation = symbolOffset + addend;
178                 break;
179             case R_386_PLT32: // this works because the address of the symbol is known at link time
180             case R_386_PC32:
181                 relocation = symbolOffset + addend - relOffset;
182                 break;
183             case R_386_TLS_LE: // The necessary value is set during storage allocation
184             case R_386_GLOB_DAT:
185             case R_386_JMP_SLOT:
186                 relocation = symbolOffset;
187                 break;
188             case R_386_TLS_GD: // The address is computed when the GOT is built
189             case R_386_GOT32: 
190             case R_386_TLS_GOTIE:
191                 result = lmap.gotSymbols.find(rel.getDynSym());
192                 if( result == lmap.gotSymbols.end() ) {
193                     errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
194                     return false;
195                 }
196
197                 relocation = result->second;
198                 break;
199             case R_386_GOTOFF:
200                 relocation = symbolOffset + addend - (lmap.gotRegionOffset + globalOffset);
201                 break;
202             case R_386_GOTPC:
203                 relocation = globalOffset + lmap.gotRegionOffset + addend - relOffset;
204                 break;
205             case R_386_TLS_IE:
206                 result = lmap.gotSymbols.find(rel.getDynSym());
207                 if( result == lmap.gotSymbols.end() ) {
208                     errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
209                     return false;
210                 }
211
212                 relocation = result->second + lmap.gotRegionOffset + globalOffset;
213                 break;
214             case R_386_COPY:
215             case R_386_RELATIVE:
216                 tmp << "ERROR: encountered relocation type(" << rel.getRelType() << 
217                        ") that is meant for use during dynamic linking";
218                 errMsg = tmp.str();
219                 return false;
220 #if defined(R_386_IRELATIVE)
221         case R_386_IRELATIVE:
222               // Consistency error; we should never try to process one of these
223               // ourselves.
224           assert(0);
225           break;
226 #endif
227             default:
228                 tmp << "Relocation type " << rel.getRelType() 
229                     << " currently unimplemented";
230                 errMsg = tmp.str();
231                 return false;
232         }
233
234         rewrite_printf("relocation = 0x%lx @ 0x%lx\n", relocation, relOffset);
235
236         memcpy(&targetData[dest], &relocation, sizeof(Elf32_Word));
237     }else if( X86_64_WIDTH == addressWidth_ ) {
238         /*
239          * Referring to the SYSV supplement:
240          *
241          * There are a few data types used by x86_64 relocations.
242          *
243          * word8 = uint8_t
244          * word16 = uint16_t
245          * word32 = Elf64_Word
246          * word64 = Elf64_Xword
247          *
248          * S = symbolOffset
249          * A = addend
250          * P = relOffset
251          * Z = symbolSize
252          *
253          * x86_64 only uses relocations that contain the addend.
254          */
255         unsigned symbolSize = rel.getDynSym()->getSize();
256
257         Elf64_Xword addend = 0;
258         if( Region::RT_RELA == rel.regionType() ) {
259             addend = rel.addend();
260         }
261
262         if( !computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset) ) {
263             return false;
264         }
265
266         rewrite_printf("relocation for '%s': TYPE = %s(%lu) S = %llx A = %llx P = %llx Z = %lx\n",
267                 rel.name().c_str(), 
268                 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
269                 rel.getRelType(),
270                 symbolOffset, addend, relOffset, symbolSize);
271
272         Offset relocation = 0;
273         unsigned fieldSize = 0; // This is set depending on the type of relocation
274         map<Symbol *, Offset>::iterator result;
275         stringstream tmp;
276
277         switch(rel.getRelType()) {
278             case R_X86_64_64:
279                 fieldSize = sizeof(Elf64_Xword);
280                 relocation = symbolOffset + addend;
281                 break;
282             case R_X86_64_PLT32:
283             case R_X86_64_PC32:
284                 fieldSize = sizeof(Elf64_Word);
285                 relocation = symbolOffset + addend - relOffset;
286                 break;
287             case R_X86_64_GOT32: // The address is computed when the GOT is built
288                 fieldSize = sizeof(Elf64_Word);
289                 result = lmap.gotSymbols.find(rel.getDynSym());
290                 if( result == lmap.gotSymbols.end() ) {
291                     errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
292                     return false;
293                 }
294
295                 relocation = result->second + addend;
296                 break;
297             case R_X86_64_TPOFF32: // The necessary value is set during storage allocation
298                 fieldSize = sizeof(Elf64_Word);
299                 relocation = symbolOffset;
300                 break;
301             case R_X86_64_GLOB_DAT:
302             case R_X86_64_JUMP_SLOT:
303                 fieldSize = sizeof(Elf64_Xword);
304                 relocation = symbolOffset;
305                 break;
306             case R_X86_64_TLSLD: // Load the symbol offset from the GOT
307             case R_X86_64_TLSGD: 
308             case R_X86_64_GOTTPOFF:
309             case R_X86_64_GOTPCREL:
310                 fieldSize = sizeof(Elf64_Word);
311
312                 result = lmap.gotSymbols.find(rel.getDynSym());
313                 if( result == lmap.gotSymbols.end() ) {
314                     errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
315                     return false;
316                 }
317
318                 relocation = result->second + lmap.gotRegionOffset + 
319                     globalOffset + addend - relOffset;
320                 break;
321             case R_X86_64_DTPOFF32:
322                 fieldSize = sizeof(Elf64_Word);
323                 relocation = addend;
324                 break;
325             case R_X86_64_32:
326             case R_X86_64_32S:
327                 fieldSize = sizeof(Elf64_Word);
328                 relocation = symbolOffset + addend;
329                 break;
330             case R_X86_64_16:
331                 fieldSize = sizeof(uint16_t);
332                 relocation = symbolOffset + addend;
333                 break;
334             case R_X86_64_PC16:
335                 fieldSize = sizeof(uint16_t);
336                 relocation = symbolOffset + addend - relOffset;
337                 break;
338             case R_X86_64_8:
339                 fieldSize = sizeof(uint8_t);
340                 relocation = symbolOffset + addend;
341                 break;
342             case R_X86_64_PC8:
343                 fieldSize = sizeof(uint8_t);
344                 relocation = symbolOffset + addend - relOffset;
345                 break;
346             case R_X86_64_RELATIVE:
347             case R_X86_64_COPY:
348                 tmp << "ERROR: encountered relocation type(" << rel.getRelType() << 
349                        ") that is meant for use during dynamic linking";
350                 errMsg = tmp.str();
351                 return false;
352 #if defined(R_X86_64_IRELATIVE)
353            case R_X86_64_IRELATIVE:
354               // Consistency error; we should never try to process one of these
355               // ourselves.
356               assert(0);
357               return false;
358 #endif
359             case R_X86_64_DTPMOD64:
360             case R_X86_64_DTPOFF64:
361             case R_X86_64_TPOFF64:
362             default:
363                 tmp << "Relocation type " << rel.getRelType() 
364                     << " currently unimplemented";
365                 errMsg = tmp.str();
366                 return false;
367         }
368
369         rewrite_printf("relocation = 0x%llx @ 0x%llx\n", relocation, relOffset);
370
371         memcpy(&targetData[dest], &relocation, fieldSize);
372     }else{
373         assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
374     }
375
376     return true;
377 }
378
379 static const string LIBC_ATEXIT_INTERNAL("__cxa_exit");
380 static const string LIBC_ATEXIT("atexit");
381
382 bool emitElfStatic::checkSpecialCaseSymbols(Symtab *member, Symbol *checkSym) {
383     /* 
384      * Special Case 1
385      *
386      * When linking code into stripped binaries, some linked functions will not
387      * work correctly because they rely on some state being initialized or
388      * updated in the original binary.
389      *
390      * For example, the libc function atexit internally keeps a list of
391      * functions to call after the main function returns. When main returns,
392      * this list is processed by libc finalization code. 
393      * 
394      * When the original binary is stripped, there is a disconnect between the
395      * atexit function in the linked code and the original atexit function.
396      * Consequently, any functionality that relies on atexit will not work
397      * (i.e. destructors for global C++ objects).
398      *
399      * The initial release of the binary rewriter for static binaries doesn't
400      * provide a solution to this problem. Therefore, a warning needs to be
401      * generated to alert the user to this outstanding problem.
402      */
403     if( isStripped_ ) {
404         if( LIBC_ATEXIT_INTERNAL == checkSym->getPrettyName() ||
405             LIBC_ATEXIT == checkSym->getPrettyName() )
406         {
407             fprintf(stderr, "WARNING: code in %s(%s) references the libc function %s.\n",
408                     member->getParentArchive()->name().c_str(),
409                     member->memberName().c_str(), checkSym->getPrettyName().c_str());
410             fprintf(stderr, "         Also, the binary to be rewritten is stripped.\n");
411             fprintf(stderr, "         Currently, the combination of these two "
412                             "is unsupported and unexpected behavior may occur.\n");
413         }
414     }
415
416     return true;
417 }
418
419 /* The TLS implementation on x86 is Variant 2 */
420
421 Offset emitElfStatic::layoutTLSImage(Offset globalOffset, Region *dataTLS, Region *bssTLS, LinkMap &lmap) {
422     return tlsLayoutVariant2(globalOffset, dataTLS, bssTLS, lmap);
423 }
424
425 Offset emitElfStatic::adjustTLSOffset(Offset curOffset, Offset tlsSize) {
426     return tlsAdjustVariant2(curOffset, tlsSize);
427 }
428
429 char emitElfStatic::getPaddingValue(Region::RegionType rtype) {
430     const char X86_NOP = 0x90;
431
432     char retChar = 0;
433     if( rtype == Region::RT_TEXT || rtype == Region::RT_TEXTDATA ) {
434         retChar = X86_NOP;
435     }
436
437     return retChar;
438 }
439
440 void emitElfStatic::cleanupTLSRegionOffsets(map<Region *, LinkMap::AllocPair> &regionAllocs,
441         Region *dataTLS, Region *bssTLS) 
442 {
443     tlsCleanupVariant2(regionAllocs, dataTLS, bssTLS);
444 }
445
446 void emitElfStatic::getExcludedSymbolNames(set<string> &symNames) {
447     /*
448      * It appears that some .o's have a reference to _GLOBAL_OFFSET_TABLE_
449      * This symbol is an indication to the linker that a GOT should be 
450      * created, it isn't a symbol that should be resolved. 
451      *
452      * Consequently, a GOT shouldn't always be created when linking 
453      * the .o's into the target. A GOT is built when certain relocations
454      * exist that require a GOT.
455      */
456     symNames.insert("_GLOBAL_OFFSET_TABLE_");
457 }
458
459 bool emitElfStatic::isGOTRelocation(unsigned long relType) {
460     if( X86_WIDTH == addressWidth_ ) {
461         switch(relType) {
462             case R_386_GOT32:
463             case R_386_TLS_IE:
464             case R_386_TLS_GOTIE:
465             case R_386_TLS_LDM:
466             case R_386_TLS_GD:
467                 return true;
468                 break;
469             default:
470                 return false;
471                 break;
472         }
473     }else if( X86_64_WIDTH == addressWidth_ ) {
474         switch(relType) {
475             case R_X86_64_TLSLD:
476             case R_X86_64_TLSGD:
477             case R_X86_64_GOTTPOFF:
478             case R_X86_64_GOT32:
479             case R_X86_64_GOTPCREL:
480                 return true;
481                 break;
482             default:
483                 return false;
484                 break;
485         }
486     }else{
487         assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
488     }
489
490     return false;
491 }
492
493 Offset emitElfStatic::getGOTSize(Symtab *, LinkMap &lmap, Offset &layoutStart) {
494     Offset size = 0;
495     layoutStart = 0;
496
497     unsigned slotSize = 0;
498     if( X86_WIDTH == addressWidth_ ) {
499         slotSize = sizeof(Elf32_Addr);
500     }else if( X86_64_WIDTH == addressWidth_ ) {
501         slotSize = sizeof(Elf64_Addr);
502     }else{
503         assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
504     }
505
506     // According to the ELF abi, entries 0, 1, 2 are reserved in a GOT on x86
507     if( lmap.gotSymbols.size() > 0 ) {
508       size = (lmap.gotSymbols.size()+GOT_RESERVED_SLOTS)*slotSize;
509     }
510
511     return size;
512 }
513
514 Offset emitElfStatic::getGOTAlign(LinkMap &) {
515     if( X86_WIDTH == addressWidth_ ) {
516         return sizeof(Elf32_Word);
517     }else if( X86_64_WIDTH == addressWidth_ ) {
518         return sizeof(Elf64_Xword);
519     }else{
520         assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
521     }
522
523     return 0;
524 }
525
526 void emitElfStatic::buildGOT(Symtab *, LinkMap &lmap) {
527     char *targetData = lmap.allocatedData;
528
529     unsigned slotSize = 0;
530     if( X86_WIDTH == addressWidth_ ) {
531         slotSize = sizeof(Elf32_Addr);
532     }else if( X86_64_WIDTH == addressWidth_ ) {
533         slotSize = sizeof(Elf64_Addr);
534     }else{
535         assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
536     }
537
538     // For each GOT symbol, allocate an entry and copy the value of the
539     // symbol into the table, additionally store the offset in the GOT
540     // back into the map
541     Offset curOffset = GOT_RESERVED_SLOTS*slotSize;
542     memset(&targetData[lmap.gotRegionOffset], 0, GOT_RESERVED_SLOTS*slotSize);
543
544     map<Symbol *, Offset>::iterator sym_it;
545     for(sym_it = lmap.gotSymbols.begin(); sym_it != lmap.gotSymbols.end(); ++sym_it) {
546         Offset value = sym_it->first->getOffset();
547         memcpy(&targetData[lmap.gotRegionOffset + curOffset], &value, slotSize);
548
549         sym_it->second = curOffset;
550
551         curOffset += slotSize;
552     }
553 }
554
555 /*
556  * .ctors and .dtors section handling
557  * 
558  * .ctors/.dtors sections are not defined by the ELF standard, LSB defines them.
559  * This is why this implementation is specific to Linux and x86.
560  *
561  * Layout of .ctors and .dtors sections on Linux x86
562  *
563  * Executable .ctors/.dtors format (size in bytes = n)
564  *
565  *  byte 0..3    byte 4..7     byte 8..11        byte n-4..n-1
566  * 0xffffffff <func. ptr 1> <func. ptr 2> ...  0x00000000
567  *
568  * Relocatable file .ctors/.dtors format (size in bytes = n)
569  *
570  *   byte 0..3         byte n-4..n-1
571  * <func. ptr 1> ... <last func. ptr>
572  *
573  * The layout is the same on Linux x86_64 except each entry is 8 bytes
574  * instead of 4. So the header and trailler are the same, but extended to
575  * 8 bytes.
576  */
577 static const Elf64_Word X86_HEADER = 0xffffffff;
578 static const Elf64_Word X86_TRAILER = 0x00000000;
579 static const Elf64_Xword X86_64_HEADER = 0xffffffffffffffffULL;
580 static const Elf64_Xword X86_64_TRAILER = 0x0000000000000000ULL;
581 static const string DTOR_NAME(".dtors");
582 static const string CTOR_NAME(".ctors");
583 static const string DTOR_NAME2(".fini_array");
584 static const string CTOR_NAME2(".init_array");
585
586 bool emitElfStatic::isConstructorRegion(Region *reg) {
587     return ( CTOR_NAME.compare(reg->getRegionName()) == 0 ||
588              CTOR_NAME2.compare(reg->getRegionName()) == 0);
589 }
590
591 bool emitElfStatic::isGOTRegion(Region *) {
592         return false;
593 }
594
595 Offset emitElfStatic::layoutNewCtorRegion(LinkMap &lmap) {
596     /* 
597      * .ctors sections are processed in reverse order on Linux x86. New .ctors
598      * sections need to be placed before the original .ctors section
599      */
600     Offset retOffset = lmap.ctorRegionOffset; 
601
602     pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
603
604     for(auto reg_it = lmap.newCtorRegions.begin(); 
605         reg_it != lmap.newCtorRegions.end(); ++reg_it) {
606       
607         result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
608
609         // If the map already contains this Region, this is a logic error
610         if( !result.second ) {
611             return ~0UL;
612         }
613
614         retOffset += (*reg_it)->getDiskSize();
615     }
616     return retOffset;
617 }
618
619 bool emitElfStatic::createNewCtorRegion(LinkMap &lmap) {
620     return true;
621 }
622
623 bool emitElfStatic::isDestructorRegion(Region *reg) {
624     return ( DTOR_NAME.compare(reg->getRegionName()) == 0 ||
625              DTOR_NAME2.compare(reg->getRegionName()) == 0);
626 }
627
628 Offset emitElfStatic::layoutNewDtorRegion(LinkMap &lmap) {
629     /*
630      * .dtors sections are processed in forward order on Linux x86. So new
631      * .dtors sections need to be placed after the original .dtors section
632      */
633     Offset retOffset = lmap.dtorRegionOffset;
634
635     pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
636
637
638     for(auto reg_it = lmap.newDtorRegions.begin(); reg_it != lmap.newDtorRegions.end(); ++reg_it) {
639         result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
640
641         // If the map already contains this Region, this is a logic error
642         if( !result.second ) {
643             return ~0UL;
644         }
645
646         retOffset += (*reg_it)->getDiskSize();
647     }
648     return retOffset;
649 }
650
651 bool emitElfStatic::createNewDtorRegion(LinkMap &lmap) {
652
653     return true;
654 }
655
656 bool emitElfStatic::updateTOC(Symtab *, LinkMap &, Offset) {
657    return true;
658 }
659
660 Offset emitElfStatic::allocStubRegions(LinkMap &lmap, Offset) {
661    // Size 0
662    return lmap.stubRegionOffset;
663 }