00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <private.h>
00025
00026 #ifndef lint
00027 static const char rcsid[] = "@(#) $Id: cook.c,v 1.1.1.1 2005/10/21 19:00:00 marcel Exp $";
00028 #endif
00029
00030 const Elf_Scn _elf_scn_init = INIT_SCN;
00031 const Scn_Data _elf_data_init = INIT_DATA;
00032
00033 Elf_Type
00034 _elf_scn_type(unsigned t) {
00035 switch (t) {
00036 case SHT_DYNAMIC: return ELF_T_DYN;
00037 case SHT_DYNSYM: return ELF_T_SYM;
00038 case SHT_HASH: return ELF_T_WORD;
00039 case SHT_REL: return ELF_T_REL;
00040 case SHT_RELA: return ELF_T_RELA;
00041 case SHT_SYMTAB: return ELF_T_SYM;
00042 case SHT_SYMTAB_SHNDX: return ELF_T_WORD;
00043 #if __LIBELF_SYMBOL_VERSIONS
00044 #if __LIBELF_SUN_SYMBOL_VERSIONS
00045 case SHT_SUNW_verdef: return ELF_T_VDEF;
00046 case SHT_SUNW_verneed: return ELF_T_VNEED;
00047 case SHT_SUNW_versym: return ELF_T_HALF;
00048 #else
00049 case SHT_GNU_verdef: return ELF_T_VDEF;
00050 case SHT_GNU_verneed: return ELF_T_VNEED;
00051 case SHT_GNU_versym: return ELF_T_HALF;
00052 #endif
00053 #endif
00054 }
00055 return ELF_T_BYTE;
00056 }
00057
00058
00059
00060
00061 #define overflow(a,b,t) (sizeof(a) < sizeof(t) && (t)(a) != (b))
00062
00063 #define truncerr(t) ((t)==ELF_T_EHDR?ERROR_TRUNC_EHDR: \
00064 ((t)==ELF_T_PHDR?ERROR_TRUNC_PHDR: \
00065 ERROR_INTERNAL))
00066 #define memerr(t) ((t)==ELF_T_EHDR?ERROR_MEM_EHDR: \
00067 ((t)==ELF_T_PHDR?ERROR_MEM_PHDR: \
00068 ERROR_INTERNAL))
00069
00070 Elf_Data*
00071 _elf_xlatetom(const Elf *elf, Elf_Data *dst, const Elf_Data *src) {
00072 if (elf->e_class == ELFCLASS32) {
00073 return elf32_xlatetom(dst, src, elf->e_encoding);
00074 }
00075 #if __LIBELF64
00076 else if (elf->e_class == ELFCLASS64) {
00077 return elf64_xlatetom(dst, src, elf->e_encoding);
00078 }
00079 #endif
00080 seterr(ERROR_UNIMPLEMENTED);
00081 return NULL;
00082 }
00083
00084 static char*
00085 _elf_item(Elf *elf, Elf_Type type, size_t n, size_t off, int *flag) {
00086 Elf_Data src, dst;
00087
00088 *flag = 0;
00089 elf_assert(n);
00090 elf_assert(valid_type(type));
00091 if (off < 0 || off > elf->e_size) {
00092 seterr(ERROR_OUTSIDE);
00093 return NULL;
00094 }
00095
00096 src.d_type = type;
00097 src.d_version = elf->e_version;
00098 src.d_size = n * _fsize(elf->e_class, src.d_version, type);
00099 elf_assert(src.d_size);
00100 if ((elf->e_size - off) < src.d_size) {
00101 seterr(truncerr(type));
00102 return NULL;
00103 }
00104
00105 dst.d_version = _elf_version;
00106 dst.d_size = n * _msize(elf->e_class, dst.d_version, type);
00107 elf_assert(dst.d_size);
00108
00109 elf_assert(elf->e_data);
00110 if (elf->e_rawdata != elf->e_data && dst.d_size <= src.d_size) {
00111 dst.d_buf = elf->e_data + off;
00112 }
00113 else if (!(dst.d_buf = malloc(dst.d_size))) {
00114 seterr(memerr(type));
00115 return NULL;
00116 }
00117 else {
00118 *flag = 1;
00119 }
00120
00121 if (elf->e_rawdata) {
00122 src.d_buf = elf->e_rawdata + off;
00123 }
00124 else {
00125 src.d_buf = elf->e_data + off;
00126 }
00127
00128 if (_elf_xlatetom(elf, &dst, &src)) {
00129 if (!*flag) {
00130 elf->e_cooked = 1;
00131 }
00132 return (char*)dst.d_buf;
00133 }
00134
00135 if (*flag) {
00136 free(dst.d_buf);
00137 *flag = 0;
00138 }
00139 return NULL;
00140 }
00141
00142 #undef truncerr
00143 #undef memerr
00144
00145 static int
00146 _elf_cook_file(Elf *elf) {
00147 size_t num, off, align_addr;
00148 int flag;
00149
00150 elf->e_ehdr = _elf_item(elf, ELF_T_EHDR, 1, 0, &flag);
00151 if (!elf->e_ehdr) {
00152 return 0;
00153 }
00154 if (flag) {
00155 elf->e_free_ehdr = 1;
00156 }
00157 align_addr = _fsize(elf->e_class, elf->e_version, ELF_T_ADDR);
00158 elf_assert(align_addr);
00159 if (elf->e_class == ELFCLASS32) {
00160 num = ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum;
00161 off = ((Elf32_Ehdr*)elf->e_ehdr)->e_phoff;
00162 }
00163 #if __LIBELF64
00164 else if (elf->e_class == ELFCLASS64) {
00165 num = ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum;
00166 off = ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff;
00167
00168
00169
00170 if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_phoff, Elf64_Off)) {
00171 seterr(ERROR_OUTSIDE);
00172 return 0;
00173 }
00174 }
00175 #endif
00176 else {
00177 seterr(ERROR_UNIMPLEMENTED);
00178 return 0;
00179 }
00180 if (num && off) {
00181 if (off % align_addr) {
00182 seterr(ERROR_ALIGN_PHDR);
00183 return 0;
00184 }
00185 elf->e_phdr = _elf_item(elf, ELF_T_PHDR, num, off, &flag);
00186 if (!elf->e_phdr) {
00187 return 0;
00188 }
00189 if (flag) {
00190 elf->e_free_phdr = 1;
00191 }
00192 elf->e_phnum = num;
00193 }
00194 if (elf->e_class == ELFCLASS32) {
00195 num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum;
00196 off = ((Elf32_Ehdr*)elf->e_ehdr)->e_shoff;
00197 }
00198 #if __LIBELF64
00199 else if (elf->e_class == ELFCLASS64) {
00200 num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum;
00201 off = ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff;
00202
00203
00204
00205 if (overflow(off, ((Elf64_Ehdr*)elf->e_ehdr)->e_shoff, Elf64_Off)) {
00206 seterr(ERROR_OUTSIDE);
00207 return 0;
00208 }
00209 }
00210 #endif
00211
00212
00213
00214
00215
00216
00217 if (off) {
00218 struct tmp {
00219 Elf_Scn scn;
00220 Scn_Data data;
00221 } *head;
00222 Elf_Data src, dst;
00223 Elf_Scn *scn;
00224 Scn_Data *sd;
00225 unsigned i;
00226
00227 if (off % align_addr) {
00228 seterr(ERROR_ALIGN_SHDR);
00229 return 0;
00230 }
00231 if (off < 0 || off > elf->e_size) {
00232 seterr(ERROR_OUTSIDE);
00233 return 0;
00234 }
00235
00236 src.d_type = ELF_T_SHDR;
00237 src.d_version = elf->e_version;
00238 src.d_size = _fsize(elf->e_class, src.d_version, ELF_T_SHDR);
00239 elf_assert(src.d_size);
00240 dst.d_version = EV_CURRENT;
00241
00242 if (num == 0) {
00243 union {
00244 Elf32_Shdr sh32;
00245 Elf64_Shdr sh64;
00246 } u;
00247
00248
00249
00250
00251
00252 if (elf->e_size - off < src.d_size) {
00253 seterr(ERROR_TRUNC_SHDR);
00254 return 0;
00255 }
00256 if (elf->e_rawdata) {
00257 src.d_buf = elf->e_rawdata + off;
00258 }
00259 else {
00260 src.d_buf = elf->e_data + off;
00261 }
00262 dst.d_buf = &u;
00263 dst.d_size = sizeof(u);
00264 if (!(_elf_xlatetom(elf, &dst, &src))) {
00265 return 0;
00266 }
00267 elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR));
00268 elf_assert(dst.d_type == ELF_T_SHDR);
00269 if (elf->e_class == ELFCLASS32) {
00270 num = u.sh32.sh_size;
00271 }
00272 #if __LIBELF64
00273 else if (elf->e_class == ELFCLASS64) {
00274 num = u.sh64.sh_size;
00275
00276
00277
00278 if (overflow(num, u.sh64.sh_size, Elf64_Xword)) {
00279 seterr(ERROR_OUTSIDE);
00280 return 0;
00281 }
00282 }
00283 #endif
00284 if (num < SHN_LORESERVE) {
00285
00286 seterr(ERROR_EHDR_SHNUM);
00287 return 0;
00288 }
00289 }
00290
00291 if ((elf->e_size - off) / src.d_size < num) {
00292 seterr(ERROR_TRUNC_SHDR);
00293 return 0;
00294 }
00295
00296 if (!(head = (struct tmp*)malloc(num * sizeof(struct tmp)))) {
00297 seterr(ERROR_MEM_SCN);
00298 return 0;
00299 }
00300 for (scn = NULL, i = num; i-- > 0; ) {
00301 head[i].scn = _elf_scn_init;
00302 head[i].data = _elf_data_init;
00303 head[i].scn.s_link = scn;
00304 if (!scn) {
00305 elf->e_scn_n = &head[i].scn;
00306 }
00307 scn = &head[i].scn;
00308 sd = &head[i].data;
00309
00310 if (elf->e_rawdata) {
00311 src.d_buf = elf->e_rawdata + off + i * src.d_size;
00312 }
00313 else {
00314 src.d_buf = elf->e_data + off + i * src.d_size;
00315 }
00316 dst.d_buf = &scn->s_uhdr;
00317 dst.d_size = sizeof(scn->s_uhdr);
00318 if (!(_elf_xlatetom(elf, &dst, &src))) {
00319 elf->e_scn_n = NULL;
00320 free(head);
00321 return 0;
00322 }
00323 elf_assert(dst.d_size == _msize(elf->e_class, EV_CURRENT, ELF_T_SHDR));
00324 elf_assert(dst.d_type == ELF_T_SHDR);
00325
00326 scn->s_elf = elf;
00327 scn->s_index = i;
00328 scn->s_data_1 = sd;
00329 scn->s_data_n = sd;
00330
00331 sd->sd_scn = scn;
00332
00333 if (elf->e_class == ELFCLASS32) {
00334 Elf32_Shdr *shdr = &scn->s_shdr32;
00335
00336 scn->s_type = shdr->sh_type;
00337 scn->s_size = shdr->sh_size;
00338 scn->s_offset = shdr->sh_offset;
00339 sd->sd_data.d_align = shdr->sh_addralign;
00340 sd->sd_data.d_type = _elf_scn_type(scn->s_type);
00341 }
00342 #if __LIBELF64
00343 else if (elf->e_class == ELFCLASS64) {
00344 Elf64_Shdr *shdr = &scn->s_shdr64;
00345
00346 scn->s_type = shdr->sh_type;
00347 scn->s_size = shdr->sh_size;
00348 scn->s_offset = shdr->sh_offset;
00349 sd->sd_data.d_align = shdr->sh_addralign;
00350
00351
00352
00353 if (overflow(scn->s_size, shdr->sh_size, Elf64_Xword)
00354 || overflow(scn->s_offset, shdr->sh_offset, Elf64_Off)
00355 || overflow(sd->sd_data.d_align, shdr->sh_addralign, Elf64_Xword)) {
00356 seterr(ERROR_OUTSIDE);
00357 return 0;
00358 }
00359 sd->sd_data.d_type = _elf_scn_type(scn->s_type);
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 if (scn->s_type == SHT_HASH) {
00378 int override = 0;
00379
00380
00381
00382
00383 if (shdr->sh_entsize == ELF64_FSZ_ADDR) {
00384 override++;
00385 }
00386
00387
00388
00389 if (shdr->sh_size % ELF64_FSZ_ADDR == 0) {
00390 override++;
00391 }
00392
00393
00394
00395 if (shdr->sh_size >= 2 * ELF64_FSZ_ADDR) {
00396 override++;
00397 }
00398
00399
00400
00401 if (shdr->sh_addralign == ELF64_FSZ_ADDR) {
00402 override++;
00403 }
00404
00405
00406
00407 if (shdr->sh_offset % ELF64_FSZ_ADDR == 0) {
00408 override++;
00409 }
00410
00411
00412
00413
00414 if (override >= 5) {
00415 sd->sd_data.d_type = ELF_T_ADDR;
00416 }
00417 }
00418
00419
00420
00421 }
00422 #endif
00423
00424
00425
00426
00427
00428
00429
00430 sd->sd_data.d_size = scn->s_size;
00431 sd->sd_data.d_version = _elf_version;
00432 }
00433 elf_assert(scn == &head[0].scn);
00434 elf->e_scn_1 = &head[0].scn;
00435 head[0].scn.s_freeme = 1;
00436 }
00437 return 1;
00438 }
00439
00440 int
00441 _elf_cook(Elf *elf) {
00442 elf_assert(_elf_scn_init.s_magic == SCN_MAGIC);
00443 elf_assert(_elf_data_init.sd_magic == DATA_MAGIC);
00444 elf_assert(elf);
00445 elf_assert(elf->e_magic == ELF_MAGIC);
00446 elf_assert(elf->e_kind == ELF_K_ELF);
00447 elf_assert(!elf->e_ehdr);
00448 if (!valid_version(elf->e_version)) {
00449 seterr(ERROR_UNKNOWN_VERSION);
00450 }
00451 else if (!valid_encoding(elf->e_encoding)) {
00452 seterr(ERROR_UNKNOWN_ENCODING);
00453 }
00454 else if (valid_class(elf->e_class)) {
00455 return _elf_cook_file(elf);
00456 }
00457 else {
00458 seterr(ERROR_UNKNOWN_CLASS);
00459 }
00460 return 0;
00461 }