00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "elf_stuff.h"
00043 #include <sys/types.h>
00044
00045 #include "defs.h"
00046 #include "symtab.h"
00047 #include "pu_info.h"
00048 #include "opcode.h"
00049 #include "wn.h"
00050 #include "wn_map.h"
00051 #include "ir_elf.h"
00052 #include "ir_bwrite.h"
00053
00054 #include "ipl_main.h"
00055 template <class ELF>
00056 static void
00057 ST_to_Elfsym (const ST* st, typename ELF::Elf_Sym& elfsym, const ELF& tag)
00058 {
00059 elfsym.st_name = ST_name_idx (st);
00060
00061 ST_SCLASS sclass = ST_sclass(st);
00062
00063 elfsym.st_value = (sclass == SCLASS_EXTERN) ? 0 : ST_ofst (st);
00064 elfsym.st_size = 0;
00065
00066 INT binding;
00067
00068 if (ST_is_weak_symbol (st)) {
00069 binding = STB_WEAK;
00070 if (ST_strong_idx (*st) != ST_st_idx (st)) {
00071 const ST &alias_base = St_Table[ST_strong_idx (*st)];
00072 sclass = ST_storage_class(alias_base);
00073 elfsym.st_value =
00074 (sclass == SCLASS_EXTERN) ? 0 : ST_ofst (alias_base);
00075 }
00076 } else
00077 binding = STB_GLOBAL;
00078
00079 INT type;
00080
00081 switch (ST_sym_class (st)) {
00082 case CLASS_VAR:
00083 type = STT_OBJECT;
00084 elfsym.st_size = TY_size (ST_type (st));
00085 switch (sclass) {
00086 case SCLASS_EXTERN:
00087 elfsym.st_shndx = SHN_UNDEF;
00088 break;
00089 case SCLASS_COMMON:
00090 elfsym.st_shndx = SHN_COMMON;
00091 elfsym.st_value = TY_align (ST_type (st));
00092 break;
00093 default:
00094 elfsym.st_shndx = SHN_MIPS_DATA;
00095 break;
00096 }
00097 break;
00098 case CLASS_FUNC:
00099 type = STT_FUNC;
00100 elfsym.st_shndx = (sclass == SCLASS_EXTERN) ? SHN_UNDEF : SHN_MIPS_TEXT;
00101 break;
00102 default:
00103 type = STT_NOTYPE;
00104 elfsym.st_shndx = (sclass == SCLASS_EXTERN) ? SHN_UNDEF : SHN_MIPS_DATA;
00105 break;
00106 }
00107
00108 elfsym.st_info = tag.Elf_st_info (binding, type);
00109
00110 switch (ST_export(st)) {
00111 case EXPORT_INTERNAL:
00112 elfsym.st_other = STO_INTERNAL;
00113 break;
00114 case EXPORT_HIDDEN:
00115 elfsym.st_other = STO_HIDDEN;
00116 break;
00117 case EXPORT_PROTECTED:
00118 elfsym.st_other = STO_PROTECTED;
00119 break;
00120 case EXPORT_OPTIONAL:
00121 elfsym.st_other = STO_OPTIONAL;
00122 break;
00123 case EXPORT_PREEMPTIBLE:
00124 default:
00125 elfsym.st_other = STO_DEFAULT;
00126 break;
00127 }
00128 }
00129
00130 namespace
00131 {
00132 template <class Sym>
00133 struct Elf_Symtab {
00134 Sym* table;
00135 UINT size;
00136 UINT max_size;
00137
00138 Elf_Symtab (UINT n) : size (1), max_size (n+1) {
00139 table = (Sym*) MEM_POOL_Alloc (Malloc_Mem_Pool,
00140 (n+1) * sizeof(Sym));
00141 bzero (table, sizeof(Sym));
00142 }
00143
00144 ~Elf_Symtab () {
00145 MEM_POOL_FREE (Malloc_Mem_Pool, table);
00146 }
00147 };
00148
00149 template <class SYMTAB, class ELF>
00150 struct st_to_elfsym {
00151 SYMTAB* symtab;
00152 const ELF& tag;
00153
00154 st_to_elfsym (SYMTAB* sym, const ELF& t) : symtab (sym), tag (t) {}
00155
00156 void operator() (UINT, const ST* st) const {
00157 if (ST_export(st) != EXPORT_LOCAL &&
00158 ST_export(st) != EXPORT_LOCAL_INTERNAL) {
00159 ST_to_Elfsym (st, symtab->table[symtab->size++], tag);
00160 }
00161 }
00162 };
00163
00164 }
00165
00166
00167
00168
00169 template <class ELF>
00170 static inline void
00171 Write_Elf_Symtab (Output_File* fl, const ELF& tag)
00172 {
00173 typedef Elf_Symtab<typename ELF::Elf_Sym> ELFSYMTAB;
00174 ELFSYMTAB symtab (ST_Table_Size (GLOBAL_SYMTAB));
00175
00176 For_all (St_Table, GLOBAL_SYMTAB,
00177 st_to_elfsym<ELFSYMTAB, ELF> (&symtab, tag));
00178
00179 #ifndef __GNUC__
00180 UINT align = __builtin_alignof(typename ELF::Elf_Sym);
00181 #else
00182 UINT align = __alignof(typename ELF::Elf_Sym);
00183 #endif
00184
00185
00186 WN_write_elf_symtab (symtab.table,
00187 symtab.size * sizeof(typename ELF::Elf_Sym),
00188 sizeof(typename ELF::Elf_Sym), align, fl);
00189 }
00190
00191 #if defined(__linux__) || defined(BUILD_OS_DARWIN)
00192 void
00193 IPL_Write_Elf_Symtab (Output_File *fl)
00194 {
00195 if (! IPL_Generate_Elf_Symtab)
00196 return;
00197
00198 #ifndef __ALWAYS_USE_64BIT_ELF__
00199 if (Use_32_Bit_Pointers)
00200 Write_Elf_Symtab (fl, ELF32());
00201 else
00202 #endif
00203 Write_Elf_Symtab (fl, ELF64());
00204 }
00205 #endif // __linux__