Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Description: 00041 * 00042 * Generate the elf headers and sections for the object file. 00043 * 00044 * ==================================================================== 00045 * ==================================================================== 00046 */ 00047 00048 00049 #include <stdio.h> 00050 #include <unistd.h> 00051 #include <fcntl.h> 00052 #include <sys/stat.h> 00053 #include <errno.h> 00054 #include <bstring.h> 00055 #include <elf.h> 00056 #include <elfaccess.h> 00057 #include <libelf.h> 00058 #include <stamp.h> 00059 #include <alloca.h> 00060 #include <assert.h> 00061 #include <cmplrs/leb128.h> 00062 #include <cmplrs/elf_interfaces.h> 00063 00064 #define USE_STANDARD_TYPES 1 00065 #include "defs.h" 00066 #include "erlib.h" 00067 #include "erglob.h" 00068 #include "config.h" 00069 #include "targ_const.h" 00070 #include "glob.h" 00071 #include "config.h" 00072 #include "config_elf_targ.h" 00073 #include "em_elf.h" 00074 #include "targ_em_elf.h" 00075 00076 00077 /* we always create the following 3 sections for all object files. */ 00078 static SCNINFO Shstrtab_Info; 00079 static SCNINFO Strtab_Info; 00080 static SCNINFO Symtab_Info_struct; 00081 /* not static because it is needed in em_dwarf.c */ 00082 pSCNINFO Symtab_Info = &Symtab_Info_struct; 00083 00084 static pSCNINFO Comment_Scn; 00085 static char *object_file_name; /* remember the .o name for the .comment scn. */ 00086 00087 /* assume we work on only one elf file at a time. If not, make Elf_Ptr 00088 a parameter to all routines that use it. 00089 */ 00090 static Elf *Elf_Ptr; 00091 00092 pSCNINFO Options_Scn; 00093 BOOL Sixtyfour_Bit; 00094 00095 /* This MAY be used by code in targ_em_elf.h 00096 */ 00097 static BOOL Big_Endian; 00098 00099 00100 /* ==================================================================== 00101 * 00102 * Increase_Data_Buffer_Size 00103 * 00104 * Increase the size of the data buffer for the section. 00105 * 00106 * NOTE: This uses realloc, which may not be the most efficient thing 00107 * to do here. 00108 * 00109 * WARNING/TODO: We can't allocate more than 32 bits of space for now. 00110 * 00111 * ==================================================================== 00112 */ 00113 00114 static void 00115 Increase_Data_Buffer_Size ( pSCNINFO scninfo, Elf64_Xword newsize ) 00116 { 00117 char *newbuf; 00118 Elf64_Word newsize32 = newsize; 00119 00120 /* If new size of buffer is zero, do nothing. */ 00121 if (newsize == 0) return; 00122 00123 /* WARNING: We can't allocate more than 32 bits of space for now. */ 00124 if ( newsize32 != newsize ) { 00125 ErrMsg ( EC_Elf_Size64, newsize, "Increase_Data_Buffer_Size" ); 00126 } 00127 00128 if ( SCNINFO_buffer(scninfo) == NULL ) { 00129 newbuf = (char *) malloc ( newsize32 ); 00130 } else { 00131 newbuf = (char *) realloc ( SCNINFO_buffer(scninfo), newsize32 ); 00132 } 00133 if ( newbuf == NULL ) { 00134 ErrMsg ( EC_No_Mem, "Increase_Data_Buffer_Size" ); 00135 } 00136 bzero ( newbuf + (INTPS) SCNINFO_limit(scninfo), 00137 newsize32 - (INT32) SCNINFO_limit(scninfo) ); 00138 00139 SCNINFO_buffer(scninfo) = newbuf; 00140 SCNINFO_limit(scninfo) = newsize32; 00141 } 00142 00143 /* Change the current location within the section */ 00144 void 00145 Em_Change_Section_Origin ( pSCNINFO scn, Elf64_Xword scn_ofst ) 00146 { 00147 SCNINFO_offset(scn) = scn_ofst; 00148 } 00149 00150 /* Change the section alignment. */ 00151 void 00152 Em_Change_Section_Alignment (pSCNINFO scn, Elf64_Word scn_align) 00153 { 00154 if (SCNINFO_align(scn) < scn_align) SCNINFO_align (scn) = scn_align; 00155 } 00156 00157 /* returns the index in the buffer where the new bytes are added. If bytes 00158 are to be added to a NOBITS section, input_buf is passed as NULL. 00159 */ 00160 Elf64_Xword 00161 Em_Add_Bytes_To_Scn ( 00162 pSCNINFO scninfo, 00163 void *input_buf, 00164 Elf64_Xword length, 00165 Elf64_Word align) 00166 { 00167 Elf64_Xword index; 00168 Elf64_Xword newoffset; 00169 Elf64_Xword newsize; 00170 00171 index = SCNINFO_offset(scninfo); 00172 /* roundup the size to the specified alignment */ 00173 index = Roundup (index, align); 00174 if (SCNINFO_align(scninfo) < align) SCNINFO_align(scninfo) = align; 00175 00176 newoffset = index + length; 00177 if (newoffset > SCNINFO_size(scninfo)) { 00178 SCNINFO_size(scninfo) = newoffset; 00179 } 00180 00181 /* If input_buf is NULL, don't actually increase the buffer size or 00182 * copy anything into the buffer. 00183 */ 00184 if (input_buf != NULL) { 00185 00186 /* WARNING: We can't allocate more than 2GB of space for now. */ 00187 newsize = newoffset + BUFSIZ; 00188 if ( (INT32)newsize != newsize ) { 00189 ErrMsg ( EC_Elf_Size64, newsize, "Em_Add_Bytes_To_Scn" ); 00190 } 00191 00192 if (newoffset > SCNINFO_limit(scninfo)) { 00193 Increase_Data_Buffer_Size (scninfo, newoffset + BUFSIZ); 00194 } 00195 if (length > 0) 00196 memcpy(SCNINFO_buffer(scninfo) + index, (char *)input_buf, length); 00197 00198 } 00199 00200 SCNINFO_offset(scninfo) = newoffset; 00201 return index; 00202 } 00203 00204 /* write out 'length' number of bytes containing zero to the section 00205 * 'scninfo' with alignment 'align. 00206 */ 00207 Elf64_Xword 00208 Em_Add_Zeros_To_Scn ( 00209 pSCNINFO scninfo, 00210 Elf64_Word length, 00211 Elf64_Word align) 00212 { 00213 Elf64_Xword index; 00214 static char *buf = NULL; 00215 static Elf64_Sword buflen = 0; 00216 00217 if ( buflen < length ) { 00218 if ( buf != NULL ) free ( buf ); 00219 buflen = length + 128; 00220 buf = (char *) calloc (buflen, 1); 00221 if (buf == NULL) 00222 ErrMsg ( EC_No_Mem, "Em_Add_Zeros_To_Scn" ); 00223 } 00224 index = Em_Add_Bytes_To_Scn (scninfo, buf, length, align); 00225 return index; 00226 } 00227 00228 00229 /* Write out an "symbol + constant" expression at the current location 00230 * in the section 'scninfo'. The 'symindex' points to the symbol and 00231 * 'addend' is the constant value. If the scninfo has the 00232 * SHF_MIPS_MERGE attribute, then emit a .rela instead of a .rel . It 00233 * is more efficient for ld to process a rela section when merging. 00234 */ 00235 Elf64_Xword 00236 Em_Add_Address_To_Scn ( 00237 pSCNINFO scninfo, 00238 Elf64_Word symindex, 00239 Elf64_Sxword addend, 00240 Elf64_Word align) 00241 { 00242 Elf64_Xword index; 00243 00244 if (Sixtyfour_Bit) { 00245 INT64 value = addend; 00246 Elf64_Shdr *scn_hdr64 = elf64_getshdr (SCNINFO_scnptr(scninfo)); 00247 00248 if (scn_hdr64->sh_flags & SHF_MERGE) { 00249 index = Em_Add_Zeros_To_Scn (scninfo, sizeof(value), align); 00250 Em_Add_New_Rela (symindex, R_WORD64, index, addend, scninfo); 00251 } 00252 else { 00253 index = Em_Add_Bytes_To_Scn (scninfo, &value, sizeof(value), align); 00254 Em_Add_New_Rel (symindex, R_WORD64, index, scninfo); 00255 } 00256 } 00257 else { 00258 INT32 value = addend; 00259 Elf32_Shdr *scn_hdr32 = elf32_getshdr (SCNINFO_scnptr(scninfo)); 00260 00261 if (scn_hdr32->sh_flags & SHF_MERGE) { 00262 index = Em_Add_Zeros_To_Scn (scninfo, sizeof(value), align); 00263 Em_Add_New_Rela (symindex, R_WORD32, index, addend, scninfo); 00264 } 00265 else { 00266 index = Em_Add_Bytes_To_Scn (scninfo, &value, sizeof(value), align); 00267 Em_Add_New_Rel (symindex, R_WORD32, index, scninfo); 00268 } 00269 } 00270 return index; 00271 } 00272 00273 /* Write out a section displacement expression at the current location 00274 * in the section 'scninfo'. The 'symindex' points to the symbol and 00275 * 'addend' is the constant value. This will be similar to a Address 00276 * expression above, but will instead be an offset from the section. 00277 */ 00278 Elf64_Xword 00279 Em_Add_Displacement_To_Scn ( 00280 pSCNINFO scninfo, 00281 Elf64_Word symindex, 00282 Elf64_Sxword addend, 00283 Elf64_Word align) 00284 { 00285 Elf64_Xword index; 00286 INT32 value = addend; 00287 00288 index = Em_Add_Bytes_To_Scn (scninfo, &value, sizeof(value), align); 00289 Em_Add_New_Rel (symindex, R_SCN_DISP, index, scninfo); 00290 return index; 00291 } 00292 00293 00294 /* check if the section name is already in the section string table. Return 00295 its index if it is already in. Otherwise add it to the string table 00296 and return the index. 00297 */ 00298 static Elf64_Word 00299 String_To_Index (pSCNINFO strinfo, char *scn_name) 00300 { 00301 Elf64_Word i; 00302 char *buf; 00303 00304 /* index 0 always points to the empty string, so return that. */ 00305 if (scn_name == NULL) return 0; 00306 00307 buf = SCNINFO_buffer(strinfo); 00308 for (i = 0; i < SCNINFO_size(strinfo); i += strlen(&buf[i]) + 1) { 00309 if (strcmp (&buf[i], scn_name) == 0) return i; 00310 } 00311 return Em_Add_Bytes_To_Scn (strinfo, scn_name, strlen(scn_name) + 1, 1); 00312 } 00313 00314 static char * 00315 Index_To_String (pSCNINFO strinfo, Elf64_Word index) 00316 { 00317 return SCNINFO_buffer(strinfo) + index; 00318 } 00319 00320 00321 /* print an error message when a libelf routine returns with an error code. */ 00322 static void 00323 print_elf_error (void) 00324 { 00325 int err; 00326 00327 err = elf_errno(); 00328 if (err != 0) ErrMsg (EC_Elf_Error, elf_errmsg (err)); 00329 } 00330 00331 00332 /* create a new section and intialize the section header. The parameters 00333 are sized for 64bit case. For 32bit case, they get truncated. 00334 */ 00335 static Elf_Scn * 00336 Create_New_Section ( 00337 char *scn_name, 00338 Elf64_Word scn_type, 00339 Elf64_Xword scn_flags, 00340 Elf64_Xword scn_entsize) 00341 { 00342 Elf_Scn *scn_ptr; 00343 Elf64_Word string_index; 00344 00345 if ((scn_ptr = elf_newscn(Elf_Ptr)) == 0) { 00346 print_elf_error (); 00347 assert(FALSE); 00348 } 00349 00350 string_index = String_To_Index (&Shstrtab_Info, scn_name); 00351 if (Sixtyfour_Bit) 00352 { 00353 Elf64_Shdr *scn_hdr64; 00354 00355 if ((scn_hdr64 = elf64_getshdr(scn_ptr)) == 0) { 00356 print_elf_error (); 00357 assert(FALSE); 00358 } 00359 scn_hdr64->sh_name = string_index; 00360 scn_hdr64->sh_type = scn_type; 00361 scn_hdr64->sh_flags = scn_flags; 00362 scn_hdr64->sh_addr = 0; 00363 scn_hdr64->sh_entsize = scn_entsize; 00364 } 00365 else { 00366 Elf32_Shdr *scn_hdr32; 00367 00368 if ((scn_hdr32 = elf32_getshdr(scn_ptr)) == 0) { 00369 print_elf_error (); 00370 assert(FALSE); 00371 } 00372 scn_hdr32->sh_name = string_index; 00373 scn_hdr32->sh_type = scn_type; 00374 scn_hdr32->sh_flags = scn_flags; 00375 scn_hdr32->sh_addr = 0; 00376 scn_hdr32->sh_entsize = scn_entsize; 00377 } 00378 return scn_ptr; 00379 } 00380 00381 /* Set the sh_link field of a section. */ 00382 void 00383 Em_Set_sh_link (pSCNINFO scn, Elf64_Word link) 00384 { 00385 if (Sixtyfour_Bit) { 00386 Elf64_Shdr *sh64; 00387 sh64 = elf64_getshdr (SCNINFO_scnptr(scn)); 00388 sh64->sh_link = link; 00389 } 00390 else { 00391 Elf32_Shdr *sh32; 00392 sh32 = elf32_getshdr (SCNINFO_scnptr(scn)); 00393 sh32->sh_link = link; 00394 } 00395 } 00396 00397 /* Set the sh_info field of a section. */ 00398 void 00399 Em_Set_sh_info (pSCNINFO scn, Elf64_Word info) 00400 { 00401 if (Sixtyfour_Bit) { 00402 Elf64_Shdr *sh64; 00403 sh64 = elf64_getshdr (SCNINFO_scnptr(scn)); 00404 sh64->sh_info = info; 00405 } 00406 else { 00407 Elf32_Shdr *sh32; 00408 sh32 = elf32_getshdr (SCNINFO_scnptr(scn)); 00409 sh32->sh_info = info; 00410 } 00411 } 00412 00413 00414 /* For a given section 'scninfo', this routine writes out the current 00415 data buffer to a Elf_Data structure. The fields in the scninfo 00416 are reset to allow for a new data buffer. 00417 */ 00418 static void Update_Data (pSCNINFO scninfo, Elf_Type type) 00419 { 00420 Elf_Data *secdata; 00421 00422 /* If there is nothing to write out then return. */ 00423 if (SCNINFO_size(scninfo) == 0) return; 00424 00425 if ((secdata = elf_newdata (SCNINFO_scnptr(scninfo))) == 0) { 00426 print_elf_error (); 00427 } 00428 00429 secdata->d_buf = SCNINFO_buffer(scninfo); 00430 secdata->d_size = SCNINFO_size(scninfo); 00431 secdata->d_type = type; 00432 secdata->d_align = SCNINFO_align(scninfo); 00433 /* reset the fields in the scninfo for a new data buffer. */ 00434 SCNINFO_buffer(scninfo) = NULL; 00435 SCNINFO_size(scninfo) = 0; 00436 SCNINFO_limit(scninfo) = 0; 00437 SCNINFO_align(scninfo) = 0; 00438 } 00439 00440 /* For a given 'scn' return its elf section index. */ 00441 size_t 00442 Em_Get_Section_Index (pSCNINFO scn) 00443 { 00444 return SCNINFO_index (scn); 00445 } 00446 00447 /* For a given 'scn' return its current offset */ 00448 Elf64_Xword 00449 Em_Get_Section_Offset (pSCNINFO scn) 00450 { 00451 return SCNINFO_offset(scn); 00452 } 00453 00454 /* return a pointer to the name of the section. */ 00455 char * 00456 Em_Get_Section_Name (pSCNINFO scninfo) 00457 { 00458 char *scnname; 00459 Elf64_Shdr *sh64; 00460 Elf32_Shdr *sh32; 00461 00462 if (Sixtyfour_Bit) { 00463 sh64 = elf64_getshdr (SCNINFO_scnptr(scninfo)); 00464 scnname = Shstrtab_Info.buffer + sh64->sh_name; 00465 } 00466 else { 00467 sh32 = elf32_getshdr (SCNINFO_scnptr(scninfo)); 00468 scnname = Shstrtab_Info.buffer + sh32->sh_name; 00469 } 00470 return scnname; 00471 } 00472 00473 Elf64_Word 00474 Em_Get_Section_Type (pSCNINFO scninfo) 00475 { 00476 if (Sixtyfour_Bit) { 00477 return elf64_getshdr(SCNINFO_scnptr(scninfo))->sh_type; 00478 } 00479 else { 00480 return elf32_getshdr(SCNINFO_scnptr(scninfo))->sh_type; 00481 } 00482 } 00483 00484 Elf64_Word 00485 Em_Get_Section_Flags (pSCNINFO scninfo) 00486 { 00487 if (Sixtyfour_Bit) { 00488 return elf64_getshdr(SCNINFO_scnptr(scninfo))->sh_flags; 00489 } 00490 else { 00491 return elf32_getshdr(SCNINFO_scnptr(scninfo))->sh_flags; 00492 } 00493 } 00494 00495 Elf64_Word 00496 Em_Get_Section_Entsize (pSCNINFO scninfo) 00497 { 00498 if (Sixtyfour_Bit) { 00499 return elf64_getshdr(SCNINFO_scnptr(scninfo))->sh_entsize; 00500 } 00501 else { 00502 return elf32_getshdr(SCNINFO_scnptr(scninfo))->sh_entsize; 00503 } 00504 } 00505 00506 Elf64_Word 00507 Em_Get_Section_Align (pSCNINFO scninfo) 00508 { 00509 if (Sixtyfour_Bit) { 00510 return elf64_getshdr(SCNINFO_scnptr(scninfo))->sh_addralign; 00511 } 00512 else { 00513 return elf32_getshdr(SCNINFO_scnptr(scninfo))->sh_addralign; 00514 } 00515 } 00516 00517 Elf64_Word 00518 Em_Get_Section_Info (pSCNINFO scninfo) 00519 { 00520 if (Sixtyfour_Bit) { 00521 return elf64_getshdr(SCNINFO_scnptr(scninfo))->sh_info; 00522 } 00523 else { 00524 return elf32_getshdr(SCNINFO_scnptr(scninfo))->sh_info; 00525 } 00526 } 00527 00528 /* create a new relocation section for 'scninfo'. The 'is_rela' argument 00529 determines if we want to create a .rela or a .rel section. 00530 */ 00531 static void 00532 Create_New_Relocation_Section (BOOL is_rela, pSCNINFO scninfo) 00533 { 00534 char *scnname; 00535 char *relname; 00536 pSCNINFO newscn; 00537 00538 scnname = Em_Get_Section_Name (scninfo); 00539 relname = (char *) alloca (strlen(scnname) + 10); 00540 if (is_rela) { 00541 strcpy (relname, ".rela"); 00542 } 00543 else { 00544 strcpy (relname, ".rel"); 00545 } 00546 strcpy (relname+strlen(relname), scnname); 00547 00548 if (is_rela) { 00549 newscn = Em_New_Section (relname, SHT_RELA, 00550 0, 00551 Sixtyfour_Bit ? sizeof(Elf64_Rela) : sizeof(Elf32_Rela), 00552 Sixtyfour_Bit ? ELF64_FSZ_XWORD : ELF32_FSZ_WORD); 00553 SCNINFO_relainfo(scninfo) = newscn; 00554 } 00555 else { 00556 newscn = Em_New_Section (relname, SHT_REL, 00557 0, 00558 Sixtyfour_Bit ? sizeof(Elf64_Rel) : sizeof(Elf32_Rel), 00559 Sixtyfour_Bit ? ELF64_FSZ_XWORD : ELF32_FSZ_WORD); 00560 SCNINFO_relinfo(scninfo) = newscn; 00561 } 00562 00563 Em_Set_sh_link (newscn, SCNINFO_index(Symtab_Info)); 00564 Em_Set_sh_info (newscn, SCNINFO_index(scninfo)); 00565 } 00566 00567 00568 /* Add a new relocation entry to the Rel section for 'scninfo'. */ 00569 void 00570 Em_Add_New_Rel ( 00571 Elf64_Word symindex, 00572 unsigned char reltype, 00573 Elf64_Addr reloffset, 00574 pSCNINFO scninfo) 00575 { 00576 if (symindex == 0) { 00577 ErrMsg (EC_Elf_Idx, symindex, "Em_Add_New_Rel"); 00578 } 00579 if (SCNINFO_relinfo(scninfo) == NULL) { 00580 Create_New_Relocation_Section (FALSE, scninfo); 00581 } 00582 if (Sixtyfour_Bit) { 00583 Elf64_Rel reloc; 00584 00585 REL_offset(reloc) = reloffset; 00586 Set_REL64_info ( reloc, symindex, reltype ); 00587 REL64_ssym(reloc) = 0; 00588 REL64_type2(reloc) = 0; 00589 REL64_type3(reloc) = 0; 00590 Em_Add_Bytes_To_Scn (SCNINFO_relinfo(scninfo), &reloc, 00591 sizeof (Elf64_Rel), ELF64_FSZ_XWORD); 00592 } 00593 else { 00594 Elf32_Rel reloc; 00595 00596 REL_offset(reloc) = reloffset; 00597 00598 /* TODO: do this under an -abi flag or something. 00599 switch (reltype) { 00600 case R_MIPS_GOT_DISP: 00601 reltype = R_MIPS_GOT16; 00602 break; 00603 case R_MIPS_GOT_PAGE: 00604 reltype = R_MIPS_GOT16; 00605 break; 00606 case R_MIPS_GOT_OFST: 00607 default: 00608 break; 00609 } 00610 */ 00611 00612 Set_REL32_info ( reloc, symindex, reltype ); 00613 Em_Add_Bytes_To_Scn (SCNINFO_relinfo(scninfo), &reloc, 00614 sizeof (Elf32_Rel), ELF32_FSZ_WORD); 00615 } 00616 } 00617 00618 00619 /* Add a new relocation entry to the Rela section for 'scninfo'. */ 00620 void 00621 Em_Add_New_Rela ( 00622 Elf64_Word symindex, 00623 unsigned char reltype, 00624 Elf64_Addr reloffset, 00625 Elf64_Sxword addend, 00626 pSCNINFO scninfo) 00627 { 00628 if (SCNINFO_relainfo(scninfo) == NULL) { 00629 Create_New_Relocation_Section (TRUE, scninfo); 00630 } 00631 if (Sixtyfour_Bit) { 00632 Elf64_Rela reloc; 00633 00634 Set_REL64_info ( reloc, symindex, reltype ); 00635 REL64_ssym(reloc) = 0; 00636 REL64_type2(reloc) = 0; 00637 REL64_type3(reloc) = 0; 00638 REL_offset(reloc) = reloffset; 00639 REL_addend(reloc) = addend; 00640 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), &reloc, 00641 sizeof (Elf64_Rela), ELF64_FSZ_XWORD); 00642 } 00643 else { 00644 Elf32_Rela reloc; 00645 00646 REL_offset(reloc) = reloffset; 00647 Set_REL32_info ( reloc, symindex, reltype ); 00648 REL_addend(reloc) = addend; 00649 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), &reloc, 00650 sizeof (Elf32_Rela), ELF32_FSZ_WORD); 00651 } 00652 } 00653 00654 00655 /* Add a new composite relocation entry to the Rela section. For the 32bit 00656 case, emit multiple relocations. 00657 */ 00658 void 00659 Em_Add_New_Composite_Rela (Elf64_Rela *preloc, pSCNINFO scninfo) 00660 { 00661 /* if nothing to do, return. */ 00662 if (REL64_type(*preloc) == R_NONE) return; 00663 00664 if (SCNINFO_relainfo(scninfo) == NULL) { 00665 Create_New_Relocation_Section (TRUE, scninfo); 00666 } 00667 00668 if (Sixtyfour_Bit) { 00669 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), preloc, 00670 sizeof (Elf64_Rela), ELF64_FSZ_XWORD); 00671 } 00672 else { 00673 Elf32_Rela reloc; 00674 00675 REL_offset(reloc) = REL_offset(*preloc); 00676 Set_REL32_info ( reloc, REL64_sym(*preloc), REL64_type(*preloc) ); 00677 REL_addend(reloc) = REL_addend(*preloc); 00678 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), &reloc, 00679 sizeof (Elf32_Rela), ELF32_FSZ_WORD); 00680 if (REL64_type2(*preloc) != 0) { 00681 Set_REL32_info (reloc, 0, REL64_type2(*preloc)); 00682 REL_addend(reloc) = 0; 00683 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), &reloc, 00684 sizeof (Elf32_Rela), ELF32_FSZ_WORD); 00685 if (REL64_type3(*preloc) != 0) { 00686 Set_REL32_info (reloc, 0, REL64_type3(*preloc)); 00687 Em_Add_Bytes_To_Scn (SCNINFO_relainfo(scninfo), &reloc, 00688 sizeof (Elf32_Rela), ELF32_FSZ_WORD); 00689 } 00690 } 00691 } 00692 } 00693 00694 00695 /* Define the symbol with index 'symindex' to have the value 'symvalue' and 00696 the size 'symsize' in the section 'scninfo'. This is to define a symbol 00697 that was earlier entered as undefined. 00698 */ 00699 void 00700 Em_Define_Symbol ( 00701 Elf64_Word symindex, 00702 Elf64_Addr symvalue, 00703 Elf64_Xword symsize, 00704 pSCNINFO scninfo) 00705 { 00706 Elf64_Half scnindex; 00707 00708 if (symindex == 0) { 00709 ErrMsg (EC_Elf_Idx, symindex, "Em_Define_Symbol"); 00710 } 00711 scnindex = SCNINFO_index(scninfo); 00712 00713 if (Sixtyfour_Bit) { 00714 Elf64_Sym *symtable; 00715 00716 symtable = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info); 00717 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) 00718 ErrMsg (EC_Elf_Idx, symindex, "Em_Define_Symbol"); 00719 symtable[symindex].st_value = symvalue; 00720 symtable[symindex].st_size = symsize; 00721 symtable[symindex].st_shndx = scnindex; 00722 } 00723 else { 00724 Elf32_Sym *symtable; 00725 00726 symtable = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info); 00727 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) 00728 ErrMsg (EC_Elf_Idx, symindex, "Em_Define_Symbol"); 00729 symtable[symindex].st_value = symvalue; 00730 symtable[symindex].st_size = symsize; 00731 symtable[symindex].st_shndx = scnindex; 00732 } 00733 } 00734 00735 /* Undefine a symbol that was previously entered */ 00736 void 00737 Em_Undefine_Symbol (Elf64_Word symindex) 00738 { 00739 if (symindex == 0) { 00740 ErrMsg (EC_Elf_Idx, symindex, "Em_Undefine_Symbol"); 00741 } 00742 if (Sixtyfour_Bit) { 00743 Elf64_Sym *symtable; 00744 00745 symtable = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info); 00746 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) 00747 ErrMsg (EC_Elf_Idx, symindex, "Em_Undefine_Symbol"); 00748 symtable[symindex].st_shndx = SHN_UNDEF; 00749 } 00750 else { 00751 Elf32_Sym *symtable; 00752 00753 symtable = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info); 00754 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) 00755 ErrMsg (EC_Elf_Idx, symindex, "Em_Undefine_Symbol"); 00756 symtable[symindex].st_shndx = SHN_UNDEF; 00757 } 00758 } 00759 00760 /* Set the binding for a symbol that was previously entered */ 00761 void 00762 Em_Set_Symbol_Binding (Elf64_Word symindex, unsigned char symbind) 00763 { 00764 if (symindex == 0) { 00765 ErrMsg (EC_Elf_Idx, symindex, "Em_Set_Symbol_Binding"); 00766 } 00767 if (Sixtyfour_Bit) { 00768 Elf64_Sym *sym64; 00769 unsigned char symtype; 00770 00771 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) { 00772 ErrMsg (EC_Elf_Idx, symindex, "Em_Set_Symbol_Binding"); 00773 } 00774 sym64 = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info) + symindex; 00775 symtype = ELF64_ST_TYPE(sym64->st_info); 00776 sym64->st_info = ELF64_ST_INFO(symbind, symtype); 00777 } 00778 else { 00779 Elf32_Sym *sym32; 00780 unsigned char symtype; 00781 00782 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) { 00783 ErrMsg (EC_Elf_Idx, symindex, "Em_Set_Symbol_Binding"); 00784 } 00785 sym32 = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info) + symindex; 00786 symtype = ELF32_ST_TYPE(sym32->st_info); 00787 sym32->st_info = ELF32_ST_INFO(symbind, symtype); 00788 } 00789 } 00790 00791 #ifndef MONGOOSE_BE 00792 Elf64_Addr 00793 Em_Get_Symbol_Value (Elf64_Word symindex) 00794 { 00795 if (Sixtyfour_Bit) { 00796 Elf64_Sym *symtable; 00797 00798 symtable = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info); 00799 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) 00800 ErrMsg (EC_Elf_Idx, symindex, "Em_Get_Symbol_Value"); 00801 return symtable[symindex].st_value; 00802 } 00803 else { 00804 Elf32_Sym *symtable; 00805 00806 symtable = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info); 00807 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) 00808 ErrMsg (EC_Elf_Idx, symindex, "Em_Get_Symbol_Value"); 00809 return symtable[symindex].st_value; 00810 } 00811 } 00812 #endif /* MONGOOSE_BE */ 00813 00814 char * 00815 Em_Get_Symbol_Name (Elf64_Word symindex) 00816 { 00817 if (Sixtyfour_Bit) { 00818 Elf64_Sym *symtable; 00819 00820 symtable = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info); 00821 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) 00822 ErrMsg (EC_Elf_Idx, symindex, "Em_Get_Symbol_Name"); 00823 return Index_To_String(&Strtab_Info, symtable[symindex].st_name); 00824 } 00825 else { 00826 Elf32_Sym *symtable; 00827 00828 symtable = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info); 00829 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) 00830 ErrMsg (EC_Elf_Idx, symindex, "Em_Get_Symbol_Name"); 00831 return Index_To_String(&Strtab_Info, symtable[symindex].st_name); 00832 } 00833 } 00834 00835 /* Add an entry to the .symtab section. Returns the index for the entry */ 00836 Elf64_Word 00837 Em_Add_New_Symbol ( 00838 char *symname, 00839 Elf64_Addr symvalue, 00840 Elf64_Xword symsize, 00841 unsigned char symbind, 00842 unsigned char symtype, 00843 unsigned char symother, 00844 Elf64_Half symshndx) 00845 { 00846 Elf64_Word strindex; 00847 Elf64_Word symindex; 00848 00849 strindex = (symname == NULL) ? 0 : 00850 (Elf64_Word) Em_Add_Bytes_To_Scn (&Strtab_Info, symname, 00851 strlen(symname)+1, sizeof(char)); 00852 if (Sixtyfour_Bit) { 00853 Elf64_Sym sym64; 00854 00855 sym64.st_name = strindex; 00856 sym64.st_value = symvalue; 00857 sym64.st_size = symsize; 00858 sym64.st_info = ELF64_ST_INFO (symbind, symtype); 00859 sym64.st_other = symother; 00860 sym64.st_shndx = symshndx; 00861 symindex = (Elf64_Word) Em_Add_Bytes_To_Scn (Symtab_Info, &sym64, 00862 sizeof (Elf64_Sym), ELF64_FSZ_XWORD); 00863 symindex /= sizeof (Elf64_Sym); 00864 } 00865 else { 00866 Elf32_Sym sym32; 00867 00868 sym32.st_name = strindex; 00869 sym32.st_value = symvalue; 00870 sym32.st_size = symsize; 00871 sym32.st_info = ELF32_ST_INFO (symbind, symtype); 00872 sym32.st_other = symother; 00873 sym32.st_shndx = symshndx; 00874 symindex = (Elf64_Word) Em_Add_Bytes_To_Scn (Symtab_Info, &sym32, 00875 sizeof (Elf32_Sym), ELF32_FSZ_WORD); 00876 symindex /= sizeof (Elf32_Sym); 00877 } 00878 return symindex; 00879 } 00880 00881 00882 #ifndef MONGOOSE_BE 00883 /* Add a new symbol with name 'symname', size 'symsize' and symbol binding 00884 'symbind' to the symbol table as a COMMON symbol. 00885 */ 00886 Elf64_Word 00887 Em_Add_New_Common_Symbol ( 00888 char *symname, 00889 Elf64_Xword symsize, 00890 unsigned char symbind, 00891 unsigned char symother) 00892 { 00893 return Em_Add_New_Symbol (symname, 0, symsize, symbind, STT_OBJECT, 00894 symother, SHN_COMMON); 00895 } 00896 #endif /* MONGOOSE_BE */ 00897 00898 /* enter a symbol with name 'symname' and type 'symtype' as undefined 00899 into the symbol table. 00900 */ 00901 Elf64_Word 00902 Em_Add_New_Undef_Symbol ( 00903 char *symname, 00904 unsigned char symbind, 00905 unsigned char symtype, 00906 unsigned char symother) 00907 { 00908 return Em_Add_New_Symbol (symname, 0, 0, symbind, symtype, 00909 symother, SHN_UNDEF); 00910 } 00911 00912 00913 /* Add a new weak symbol entry with the name 'weakname'. Use the same 00914 attributes as the symbol table entry with index 'symindex'. 00915 */ 00916 Elf64_Word 00917 Em_Add_New_Weak_Symbol ( 00918 char *weakname, 00919 unsigned char symtype, 00920 unsigned char symother, 00921 Elf64_Word symindex) 00922 { 00923 if (symindex == 0) { 00924 ErrMsg (EC_Elf_Idx, symindex, "Em_Add_New_Weak_Symbol"); 00925 } 00926 if (Sixtyfour_Bit) { 00927 Elf64_Sym *symtable; 00928 00929 symtable = (Elf64_Sym *)SCNINFO_buffer(Symtab_Info); 00930 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf64_Sym))) 00931 ErrMsg (EC_Elf_Idx, symindex, "Em_Add_New_Weak_Symbol"); 00932 return Em_Add_New_Symbol (weakname, symtable[symindex].st_value, 00933 symtable[symindex].st_size, STB_WEAK, 00934 symtype, symother, 00935 symtable[symindex].st_shndx); 00936 } 00937 else { 00938 Elf32_Sym *symtable; 00939 00940 symtable = (Elf32_Sym *)SCNINFO_buffer(Symtab_Info); 00941 if (symindex >= (SCNINFO_size(Symtab_Info) / sizeof(Elf32_Sym))) 00942 ErrMsg (EC_Elf_Idx, symindex, "Em_Add_New_Weak_Symbol"); 00943 return Em_Add_New_Symbol (weakname, symtable[symindex].st_value, 00944 symtable[symindex].st_size, STB_WEAK, 00945 symtype, symother, 00946 symtable[symindex].st_shndx); 00947 } 00948 } 00949 00950 00951 00952 /* Update the size field of the last EK_ADDR_RESET entry in 'ev_scn'. */ 00953 static void 00954 Update_Addr_Reset_Size (pSCNINFO ev_scn) 00955 { 00956 UINT16 size; 00957 INT size_index; 00958 00959 size = SCNINFO_offset(ev_scn) - SCNINFO_ev_offset(ev_scn); 00960 size_index = SCNINFO_ev_offset(ev_scn) + 5; 00961 SCNINFO_buffer(ev_scn)[size_index] = (size >> 8); 00962 SCNINFO_buffer(ev_scn)[size_index+1] = (size & 0xff); 00963 } 00964 00965 /* Emit an EK_ADDR_RESET opcode into either the .events section or the 00966 * .contents section. 00967 */ 00968 void 00969 Generate_Addr_Reset (pSCNINFO scn, BOOL is_events, Elf64_Xword ev_ofst) 00970 { 00971 Elf64_Xword evscn_ofst; 00972 char opcode = EK_ADDR_RESET; 00973 Elf64_Xword dummy = 0; 00974 pSCNINFO events_scn; 00975 Elf64_Word short_ofst = ev_ofst; 00976 00977 if ( short_ofst != ev_ofst ) { 00978 ErrMsg ( EC_Elf_Ofst64, ev_ofst, "Generate_Addr_Reset" ); 00979 } 00980 00981 events_scn = (is_events) ? SCNINFO_events(scn) : SCNINFO_contents(scn); 00982 /* Use the ev_offset field of the .events or .contents section to 00983 * keep the address of the last EK_ADDR_RESET entry. 00984 */ 00985 SCNINFO_ev_offset(events_scn) = (Elf64_Word) 00986 Em_Add_Bytes_To_Scn (events_scn, &opcode, 1, 1); 00987 evscn_ofst = Em_Add_Bytes_To_Scn (events_scn, &short_ofst, 4, 1); 00988 Em_Add_New_Rel (Em_Create_Section_Symbol(scn), R_SCN_DISP, 00989 evscn_ofst, events_scn); 00990 /* Place holder for the number of bytes till next EK_ADDR_RESET */ 00991 Em_Add_Bytes_To_Scn (events_scn, &dummy, 2, 1); 00992 if (is_events) 00993 SCNINFO_ev_offset(scn) = ev_ofst; 00994 else 00995 SCNINFO_con_offset(scn) = ev_ofst; 00996 } 00997 00998 /* The maximum number of bytes in the .events section between two 00999 EK_ADDR_RESET entries. 01000 */ 01001 #define MAX_EV_SIZE 64000 01002 01003 void 01004 Set_Current_Location (pSCNINFO scn, BOOL is_events, Elf64_Word ev_ofst) 01005 { 01006 Elf64_Word cur_ofst, word_ofst; 01007 char opcode; 01008 pSCNINFO ev_scn; 01009 char leb_buf[10]; 01010 UINT32 num_bytes; 01011 01012 01013 ev_scn = (is_events) ? SCNINFO_events(scn) : SCNINFO_contents(scn); 01014 01015 /* Check if we need to insert another EK_ADDR_RESET entry. */ 01016 if ((SCNINFO_offset(ev_scn) - SCNINFO_ev_offset(ev_scn)) > MAX_EV_SIZE) { 01017 Update_Addr_Reset_Size (ev_scn); 01018 Generate_Addr_Reset ( scn, is_events, (Elf64_Xword)ev_ofst ); 01019 return; 01020 } 01021 01022 cur_ofst = (is_events) ? SCNINFO_ev_offset(scn) : SCNINFO_con_offset(scn); 01023 if (ev_ofst < cur_ofst) { 01024 // don't think this can happen, but just to be sure.... 01025 Update_Addr_Reset_Size (ev_scn); 01026 Generate_Addr_Reset ( scn, is_events, (Elf64_Xword)ev_ofst ); 01027 return; 01028 } 01029 if ((ev_ofst - cur_ofst) > MAX_EV_SIZE) { 01030 // don't think this can happen, but just to be sure.... 01031 Update_Addr_Reset_Size (ev_scn); 01032 Generate_Addr_Reset ( scn, is_events, (Elf64_Xword)ev_ofst ); 01033 return; 01034 } 01035 /* If already at the right place, don't do anything. */ 01036 if (ev_ofst == cur_ofst) return; 01037 01038 word_ofst = (ev_ofst - cur_ofst) >> 2; 01039 if (word_ofst <= 127) { 01040 opcode = EK_INCR_LOC | (word_ofst & 0x7f); 01041 Em_Add_Bytes_To_Scn (ev_scn, &opcode, 1, 1); 01042 } else { 01043 opcode = EK_INCR_LOC_EXT; 01044 Em_Add_Bytes_To_Scn (ev_scn, &opcode, 1, 1); 01045 num_bytes = _leb128_unsigned_encode32 (word_ofst, leb_buf); 01046 Em_Add_Bytes_To_Scn (ev_scn, leb_buf, num_bytes, 1); 01047 } 01048 if ( is_events) 01049 SCNINFO_ev_offset(scn) = ev_ofst; 01050 else 01051 SCNINFO_con_offset(scn) = ev_ofst; 01052 } 01053 01054 01055 /* Add an interface descriptor to the .interfaces section. */ 01056 01057 void 01058 Em_Add_New_Interface ( 01059 Elf64_Word length, 01060 Elf64_Byte *data ) 01061 { 01062 if ( Interface_Scn == NULL) { 01063 Interface_Scn = Em_New_Section (SECT_IFACE_NAME, SHT_IRIX_IFACE, 01064 SHF_NOSTRIP, ELF32_FSZ_WORD, ELF32_FSZ_WORD); 01065 Em_Set_sh_link (Interface_Scn, SCNINFO_index(Symtab_Info)); 01066 } 01067 Em_Add_Bytes_To_Scn (Interface_Scn, data, length, ELF32_FSZ_WORD); 01068 } 01069 01070 /* Add a comment string; 01071 * if the string contains no colons (':'), 01072 * then assume we are only passing the toolname, 01073 * and this routine will go ahead and add the version information. 01074 * E.g. can pass "be" or "be::4.00:". 01075 */ 01076 extern void 01077 Em_Add_Comment (char *s) 01078 { 01079 char *buff; 01080 if (Comment_Scn == NULL) { 01081 Comment_Scn = Em_New_Section (ELF_COMMENT, SHT_PROGBITS, 01082 0, 0, sizeof(char)); 01083 } 01084 if (strchr(s,':') == NULL) { 01085 buff = (char *) alloca (strlen(s) + sizeof(INCLUDE_STAMP) + 01086 strlen(object_file_name) + 4); 01087 sprintf(buff, "%s::%s:%s", s, INCLUDE_STAMP, object_file_name); 01088 } else { 01089 buff = s; 01090 } 01091 Em_Add_Bytes_To_Scn (Comment_Scn, buff, strlen(buff) + 1, sizeof(char)); 01092 } 01093 01094 /* Create the ELF header, section string table, the symbol table 01095 section and the symbol string table. 01096 */ 01097 static void 01098 Create_Elf_Header (INT isa, BOOL old_abi, BOOL big_endian, BOOL pic, 01099 BOOL cpic, BOOL xgot, BOOL gp_groups) 01100 { 01101 unsigned char e_ident_data; 01102 Elf64_Word e_flags; 01103 Elf32_Ehdr *ehdr32; 01104 Elf64_Ehdr *ehdr64; 01105 01106 01107 /* which target architecture */ 01108 e_flags = Config_ELF_From_Target (Sixtyfour_Bit, old_abi, isa); 01109 01110 /* set the PIC flags. */ 01111 if (pic) 01112 e_flags |= EF_MIPS_PIC; 01113 else if (cpic) 01114 e_flags |= EF_MIPS_CPIC; 01115 if (xgot) 01116 e_flags |= EF_MIPS_XGOT; 01117 if (gp_groups) 01118 e_flags |= EF_MIPS_OPTIONS_FIRST; 01119 01120 /* what endian is this? */ 01121 e_ident_data = (big_endian ? ELFDATA2MSB : ELFDATA2LSB); 01122 01123 if (Sixtyfour_Bit) { 01124 ehdr64 = elf64_newehdr(Elf_Ptr); 01125 ehdr64->e_ident[EI_DATA] = e_ident_data; 01126 Set_Elf_Version ((unsigned char *) &(ehdr64->e_ident)); 01127 ehdr64->e_machine = Get_Elf_Target_Machine(); 01128 ehdr64->e_type = ET_REL; 01129 #ifndef linux 01130 ehdr64->e_flags = e_flags; 01131 #else 01132 ehdr64->e_flags = 0x23000000LL | e_flags; 01133 #endif 01134 } 01135 else { 01136 ehdr32 = elf32_newehdr(Elf_Ptr); 01137 ehdr32->e_ident[EI_DATA] = e_ident_data; 01138 Set_Elf_Version ((unsigned char *) &(ehdr32->e_ident)); 01139 ehdr32->e_machine = Get_Elf_Target_Machine(); 01140 ehdr32->e_type = ET_REL; 01141 ehdr32->e_flags = e_flags; 01142 } 01143 01144 /* allocate an empty string at the start of the string tables. 01145 This is for entries that have string table index of 0. 01146 */ 01147 (void) Em_Add_Bytes_To_Scn (&Shstrtab_Info, "", 1, 1); 01148 (void) Em_Add_Bytes_To_Scn (&Strtab_Info, "", 1, 1); 01149 01150 /* create symbol table section */ 01151 SCNINFO_scnptr(Symtab_Info) = 01152 Create_New_Section (ELF_SYMTAB, SHT_SYMTAB, SHF_ALLOC , 01153 Sixtyfour_Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym)); 01154 01155 /* add an empty entry to the symbol table as the first entry */ 01156 Em_Add_New_Symbol (NULL, 0, 0, STB_LOCAL, STT_NOTYPE, 0, SHN_UNDEF); 01157 01158 /* create section string tbl */ 01159 Shstrtab_Info.scnptr = Create_New_Section (ELF_SHSTRTAB, SHT_STRTAB, 01160 SHF_ALLOC, sizeof(char)); 01161 01162 /* create symbol string tbl */ 01163 Strtab_Info.scnptr = Create_New_Section (ELF_STRTAB, SHT_STRTAB, 01164 SHF_ALLOC, sizeof(char)); 01165 01166 Em_Set_sh_link (Symtab_Info, SCNINFO_index(&Strtab_Info)); 01167 if (Sixtyfour_Bit) { 01168 ehdr64->e_shstrndx = SCNINFO_index(&Shstrtab_Info); 01169 } 01170 else { 01171 ehdr32->e_shstrndx = SCNINFO_index(&Shstrtab_Info); 01172 } 01173 } 01174 01175 01176 static void 01177 Read_Section (pSCNINFO scninfo, Elf64_Word scndx) 01178 { 01179 Elf_Data *scndata; 01180 Elf_Scn *scn; 01181 01182 /* initialize the SCNINFO to all zeros */ 01183 bzero (scninfo, sizeof(SCNINFO)); 01184 scn = elf_getscn (Elf_Ptr, scndx); 01185 scndata = elf_getdata (scn, (Elf_Data *)0); 01186 elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); 01187 elf_flagdata (scndata, ELF_C_SET, ELF_F_DIRTY); 01188 SCNINFO_scnptr(scninfo) = scn; 01189 Em_Add_Bytes_To_Scn (scninfo, scndata->d_buf, scndata->d_size, 01190 scndata->d_align); 01191 scndata->d_buf = NULL; 01192 scndata->d_size = 0; 01193 } 01194 01195 01196 static void 01197 Read_Elf_File (void) 01198 { 01199 Elf64_Word shndx; 01200 Elf64_Word scntype; 01201 Elf_Scn *scn; 01202 01203 shndx = (Sixtyfour_Bit) ? elf64_getehdr(Elf_Ptr)->e_shstrndx : 01204 elf32_getehdr(Elf_Ptr)->e_shstrndx; 01205 Read_Section (&Shstrtab_Info, shndx); 01206 01207 scn = NULL; 01208 while ((scn = elf_nextscn (Elf_Ptr, scn)) != NULL) { 01209 scntype = (Sixtyfour_Bit) ? elf64_getshdr(scn)->sh_type : 01210 elf32_getshdr(scn)->sh_type; 01211 if (scntype == SHT_SYMTAB) { 01212 Read_Section (Symtab_Info, elf_ndxscn(scn)); 01213 shndx = (Sixtyfour_Bit) ? elf64_getshdr(scn)->sh_link : 01214 elf32_getshdr(scn)->sh_link; 01215 Read_Section (&Strtab_Info, shndx); 01216 break; 01217 } 01218 } 01219 } 01220 01221 01222 /* returns the file descriptor for the file opened. */ 01223 int Em_Begin_File ( 01224 char *ofilename, 01225 BOOL update, 01226 BOOL elf64, 01227 BOOL old_abi, 01228 INT isa, 01229 BOOL big_endian, 01230 BOOL pic, 01231 BOOL cpic, 01232 BOOL xgot, 01233 BOOL gp_groups, 01234 BOOL elf_trace) 01235 { 01236 int ofiledes; 01237 Elf_Cmd cmd; 01238 01239 /* init various sections */ 01240 Options_Scn = NULL; 01241 Comment_Scn = NULL; 01242 Interface_Scn = NULL; 01243 01244 Sixtyfour_Bit = elf64; 01245 Big_Endian = big_endian; 01246 if (update) { 01247 ofiledes = open (ofilename, O_RDWR); 01248 } 01249 else { 01250 INT result; 01251 struct stat statstuff; 01252 01253 result = stat (ofilename, &statstuff); 01254 /* If the file already exists, delete it. */ 01255 if (result != -1) { 01256 /* it exists */ 01257 result = unlink (ofilename); 01258 if (result == -1) { 01259 ErrMsg (EC_Obj_Delete, ofilename, errno); 01260 return (int) 0; 01261 } 01262 } 01263 ofiledes = open (ofilename, O_RDWR|O_TRUNC|O_CREAT, 0666); 01264 } 01265 if (ofiledes <= 0) { 01266 ErrMsg (EC_Obj_Create, ofilename, errno); 01267 return (int) 0; 01268 } 01269 01270 object_file_name = ofilename; 01271 01272 /* reset the elf error number */ 01273 (void)elf_errno(); 01274 /* check that we are not using an older version of libelf. */ 01275 if (elf_version(EV_CURRENT) == EV_NONE) { 01276 print_elf_error (); 01277 } 01278 cmd = update ? ELF_C_RDWR : ELF_C_WRITE; 01279 if ((Elf_Ptr = elf_begin(ofiledes, cmd, (Elf * )0)) == 0) { 01280 print_elf_error (); 01281 } 01282 01283 if (update) { 01284 Read_Elf_File (); 01285 } 01286 else { 01287 Create_Elf_Header (isa, old_abi, big_endian, pic, cpic, xgot, gp_groups); 01288 } 01289 return ofiledes; 01290 } 01291 01292 01293 /* update the elf object file */ 01294 void 01295 Em_End_File (void) 01296 { 01297 /* write out the .shstrtab data */ 01298 Update_Data (&Shstrtab_Info, ELF_T_BYTE); 01299 /* write out the .strtab data */ 01300 Update_Data (&Strtab_Info, ELF_T_BYTE); 01301 /* write out the .symtab data */ 01302 Update_Data (Symtab_Info, ELF_T_SYM); 01303 01304 /* write out the .options data */ 01305 if (Options_Scn != NULL) Em_End_Section (Options_Scn); 01306 /* write out the .comment data */ 01307 if (Comment_Scn != NULL) Em_End_Section (Comment_Scn); 01308 /* write out the .interface data */ 01309 if (Interface_Scn != NULL) Em_End_Section (Interface_Scn); 01310 01311 if (elf_update(Elf_Ptr, ELF_C_WRITE) == -1 || 01312 elf_end(Elf_Ptr) == 0) 01313 { 01314 print_elf_error (); 01315 } 01316 } 01317 01318 01319 pSCNINFO Em_New_Section ( 01320 char *scnname, 01321 Elf64_Word scntype, 01322 Elf64_Xword scnflags, 01323 Elf64_Xword scnentsize, 01324 Elf64_Xword scnalign) 01325 { 01326 Elf_Scn *scn; 01327 pSCNINFO scninfo; 01328 01329 scninfo = (pSCNINFO) malloc (sizeof (SCNINFO)); 01330 if (scninfo == NULL) 01331 ErrMsg ( EC_No_Mem, "Em_New_Section" ); 01332 bzero (scninfo, sizeof(SCNINFO)); 01333 scn = Create_New_Section (scnname, scntype, scnflags, scnentsize); 01334 SCNINFO_scnptr(scninfo) = scn; 01335 SCNINFO_align(scninfo) = scnalign; 01336 return scninfo; 01337 } 01338 01339 01340 void 01341 Em_End_Section (pSCNINFO scninfo) 01342 { 01343 Update_Data (scninfo, ELF_T_BYTE); 01344 if (SCNINFO_relinfo(scninfo) != NULL) { 01345 Update_Data (SCNINFO_relinfo(scninfo), ELF_T_REL); 01346 free (SCNINFO_relinfo(scninfo)); 01347 } 01348 if (SCNINFO_relainfo(scninfo) != NULL) { 01349 Update_Data (SCNINFO_relainfo(scninfo), ELF_T_RELA); 01350 free (SCNINFO_relainfo(scninfo)); 01351 } 01352 if (SCNINFO_events(scninfo) != NULL) { 01353 Update_Addr_Reset_Size (SCNINFO_events(scninfo)); 01354 Em_End_Section (SCNINFO_events(scninfo)); 01355 } 01356 if (SCNINFO_contents(scninfo) != NULL) { 01357 Update_Addr_Reset_Size (SCNINFO_contents(scninfo)); 01358 Em_End_Section (SCNINFO_contents(scninfo)); 01359 } 01360 free (scninfo); 01361 } 01362 01363 /* Allocate a new data buffer of 'size'. */ 01364 void Em_New_Data_Buffer (pSCNINFO scninfo, Elf64_Xword size, int alignment) 01365 { 01366 Elf64_Xword newoffset; 01367 01368 newoffset = SCNINFO_size(scninfo); 01369 newoffset = Roundup (newoffset, alignment); 01370 if (SCNINFO_align(scninfo) < alignment) 01371 SCNINFO_align(scninfo) = alignment; 01372 Increase_Data_Buffer_Size ( scninfo, newoffset + size ); 01373 } 01374 01375 Elf64_Word 01376 Em_Create_Section_Symbol (pSCNINFO scninfo) 01377 { 01378 Elf64_Word symindex; 01379 01380 symindex = SCNINFO_scnidx(scninfo); 01381 if (symindex == 0) { 01382 symindex = Em_Add_New_Symbol (Em_Get_Section_Name (scninfo), 01383 (Elf64_Addr)0, (Elf64_Xword)0, 01384 STB_LOCAL, STT_SECTION, 0, 01385 SCNINFO_index(scninfo)); 01386 SCNINFO_scnidx(scninfo) = symindex; 01387 } 01388 return symindex; 01389 }