Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
em_elf.cxx
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines