github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/ld/ldpe.c (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "l.h" 6 #include "lib.h" 7 #include "../ld/pe.h" 8 9 #define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 10 11 #define IMAGE_SYM_UNDEFINED 0 12 #define IMAGE_SYM_ABSOLUTE (-1) 13 #define IMAGE_SYM_DEBUG (-2) 14 #define IMAGE_SYM_TYPE_NULL 0 15 #define IMAGE_SYM_TYPE_VOID 1 16 #define IMAGE_SYM_TYPE_CHAR 2 17 #define IMAGE_SYM_TYPE_SHORT 3 18 #define IMAGE_SYM_TYPE_INT 4 19 #define IMAGE_SYM_TYPE_LONG 5 20 #define IMAGE_SYM_TYPE_FLOAT 6 21 #define IMAGE_SYM_TYPE_DOUBLE 7 22 #define IMAGE_SYM_TYPE_STRUCT 8 23 #define IMAGE_SYM_TYPE_UNION 9 24 #define IMAGE_SYM_TYPE_ENUM 10 25 #define IMAGE_SYM_TYPE_MOE 11 26 #define IMAGE_SYM_TYPE_BYTE 12 27 #define IMAGE_SYM_TYPE_WORD 13 28 #define IMAGE_SYM_TYPE_UINT 14 29 #define IMAGE_SYM_TYPE_DWORD 15 30 #define IMAGE_SYM_TYPE_PCODE 32768 31 #define IMAGE_SYM_DTYPE_NULL 0 32 #define IMAGE_SYM_DTYPE_POINTER 0x10 33 #define IMAGE_SYM_DTYPE_FUNCTION 0x20 34 #define IMAGE_SYM_DTYPE_ARRAY 0x30 35 #define IMAGE_SYM_CLASS_END_OF_FUNCTION (-1) 36 #define IMAGE_SYM_CLASS_NULL 0 37 #define IMAGE_SYM_CLASS_AUTOMATIC 1 38 #define IMAGE_SYM_CLASS_EXTERNAL 2 39 #define IMAGE_SYM_CLASS_STATIC 3 40 #define IMAGE_SYM_CLASS_REGISTER 4 41 #define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 42 #define IMAGE_SYM_CLASS_LABEL 6 43 #define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 44 #define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 45 #define IMAGE_SYM_CLASS_ARGUMENT 9 46 #define IMAGE_SYM_CLASS_STRUCT_TAG 10 47 #define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 48 #define IMAGE_SYM_CLASS_UNION_TAG 12 49 #define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 50 #define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 51 #define IMAGE_SYM_CLASS_ENUM_TAG 15 52 #define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 53 #define IMAGE_SYM_CLASS_REGISTER_PARAM 17 54 #define IMAGE_SYM_CLASS_BIT_FIELD 18 55 #define IMAGE_SYM_CLASS_FAR_EXTERNAL 68 /* Not in PECOFF v8 spec */ 56 #define IMAGE_SYM_CLASS_BLOCK 100 57 #define IMAGE_SYM_CLASS_FUNCTION 101 58 #define IMAGE_SYM_CLASS_END_OF_STRUCT 102 59 #define IMAGE_SYM_CLASS_FILE 103 60 #define IMAGE_SYM_CLASS_SECTION 104 61 #define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 62 #define IMAGE_SYM_CLASS_CLR_TOKEN 107 63 64 #define IMAGE_REL_I386_ABSOLUTE 0x0000 65 #define IMAGE_REL_I386_DIR16 0x0001 66 #define IMAGE_REL_I386_REL16 0x0002 67 #define IMAGE_REL_I386_DIR32 0x0006 68 #define IMAGE_REL_I386_DIR32NB 0x0007 69 #define IMAGE_REL_I386_SEG12 0x0009 70 #define IMAGE_REL_I386_SECTION 0x000A 71 #define IMAGE_REL_I386_SECREL 0x000B 72 #define IMAGE_REL_I386_TOKEN 0x000C 73 #define IMAGE_REL_I386_SECREL7 0x000D 74 #define IMAGE_REL_I386_REL32 0x0014 75 76 #define IMAGE_REL_AMD64_ABSOLUTE 0x0000 77 #define IMAGE_REL_AMD64_ADDR64 0x0001 // R_X86_64_64 78 #define IMAGE_REL_AMD64_ADDR32 0x0002 // R_X86_64_PC32 79 #define IMAGE_REL_AMD64_ADDR32NB 0x0003 80 #define IMAGE_REL_AMD64_REL32 0x0004 81 #define IMAGE_REL_AMD64_REL32_1 0x0005 82 #define IMAGE_REL_AMD64_REL32_2 0x0006 83 #define IMAGE_REL_AMD64_REL32_3 0x0007 84 #define IMAGE_REL_AMD64_REL32_4 0x0008 85 #define IMAGE_REL_AMD64_REL32_5 0x0009 86 #define IMAGE_REL_AMD64_SECTION 0x000A 87 #define IMAGE_REL_AMD64_SECREL 0x000B 88 #define IMAGE_REL_AMD64_SECREL7 0x000C 89 #define IMAGE_REL_AMD64_TOKEN 0x000D 90 #define IMAGE_REL_AMD64_SREL32 0x000E 91 #define IMAGE_REL_AMD64_PAIR 0x000F 92 #define IMAGE_REL_AMD64_SSPAN32 0x0010 93 94 typedef struct PeSym PeSym; 95 typedef struct PeSect PeSect; 96 typedef struct PeObj PeObj; 97 98 struct PeSym { 99 char* name; 100 uint32 value; 101 uint16 sectnum; 102 uint16 type; 103 uint8 sclass; 104 uint8 aux; 105 Sym* sym; 106 }; 107 108 struct PeSect { 109 char* name; 110 uchar* base; 111 uint64 size; 112 Sym* sym; 113 IMAGE_SECTION_HEADER sh; 114 }; 115 116 struct PeObj { 117 Biobuf *f; 118 char *name; 119 uint32 base; 120 121 PeSect *sect; 122 uint nsect; 123 PeSym *pesym; 124 uint npesym; 125 126 IMAGE_FILE_HEADER fh; 127 char* snames; 128 }; 129 130 static int map(PeObj *obj, PeSect *sect); 131 static int readsym(PeObj *obj, int i, PeSym **sym); 132 133 void 134 ldpe(Biobuf *f, char *pkg, int64 len, char *pn) 135 { 136 char *name; 137 int32 base; 138 uint32 l; 139 int i, j, numaux; 140 PeObj *obj; 141 PeSect *sect, *rsect; 142 IMAGE_SECTION_HEADER sh; 143 uchar symbuf[18]; 144 Sym *s; 145 Reloc *r, *rp; 146 PeSym *sym; 147 148 USED(len); 149 if(debug['v']) 150 Bprint(&bso, "%5.2f ldpe %s\n", cputime(), pn); 151 152 sect = nil; 153 version++; 154 base = Boffset(f); 155 156 obj = mal(sizeof *obj); 157 obj->f = f; 158 obj->base = base; 159 obj->name = pn; 160 // read header 161 if(Bread(f, &obj->fh, sizeof obj->fh) != sizeof obj->fh) 162 goto bad; 163 // load section list 164 obj->sect = mal(obj->fh.NumberOfSections*sizeof obj->sect[0]); 165 obj->nsect = obj->fh.NumberOfSections; 166 for(i=0; i < obj->fh.NumberOfSections; i++) { 167 if(Bread(f, &obj->sect[i].sh, sizeof sh) != sizeof sh) 168 goto bad; 169 obj->sect[i].size = obj->sect[i].sh.SizeOfRawData; 170 obj->sect[i].name = (char*)obj->sect[i].sh.Name; 171 // TODO return error if found .cormeta 172 } 173 // load string table 174 Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0); 175 if(Bread(f, symbuf, 4) != 4) 176 goto bad; 177 l = le32(symbuf); 178 obj->snames = mal(l); 179 Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0); 180 if(Bread(f, obj->snames, l) != l) 181 goto bad; 182 // read symbols 183 obj->pesym = mal(obj->fh.NumberOfSymbols*sizeof obj->pesym[0]); 184 obj->npesym = obj->fh.NumberOfSymbols; 185 Bseek(f, base+obj->fh.PointerToSymbolTable, 0); 186 for(i=0; i<obj->fh.NumberOfSymbols; i+=numaux+1) { 187 Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*i, 0); 188 if(Bread(f, symbuf, sizeof symbuf) != sizeof symbuf) 189 goto bad; 190 191 if((symbuf[0] == 0) && (symbuf[1] == 0) && 192 (symbuf[2] == 0) && (symbuf[3] == 0)) { 193 l = le32(&symbuf[4]); 194 obj->pesym[i].name = (char*)&obj->snames[l]; 195 } else { // sym name length <= 8 196 obj->pesym[i].name = mal(9); 197 strncpy(obj->pesym[i].name, (char*)symbuf, 8); 198 obj->pesym[i].name[8] = 0; 199 } 200 obj->pesym[i].value = le32(&symbuf[8]); 201 obj->pesym[i].sectnum = le16(&symbuf[12]); 202 obj->pesym[i].sclass = symbuf[16]; 203 obj->pesym[i].aux = symbuf[17]; 204 obj->pesym[i].type = le16(&symbuf[14]); 205 numaux = obj->pesym[i].aux; 206 if (numaux < 0) 207 numaux = 0; 208 } 209 // create symbols for mapped sections 210 for(i=0; i<obj->nsect; i++) { 211 sect = &obj->sect[i]; 212 if(sect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) 213 continue; 214 215 if((sect->sh.Characteristics&(IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_CNT_UNINITIALIZED_DATA)) == 0) { 216 // This has been seen for .idata sections, which we 217 // want to ignore. See issues 5106 and 5273. 218 continue; 219 } 220 221 if(map(obj, sect) < 0) 222 goto bad; 223 224 name = smprint("%s(%s)", pkg, sect->name); 225 s = lookup(name, version); 226 free(name); 227 switch(sect->sh.Characteristics&(IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_CNT_INITIALIZED_DATA| 228 IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE)) { 229 case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ: //.rdata 230 s->type = SRODATA; 231 break; 232 case IMAGE_SCN_CNT_UNINITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.bss 233 s->type = SBSS; 234 break; 235 case IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE: //.data 236 s->type = SDATA; 237 break; 238 case IMAGE_SCN_CNT_CODE|IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ: //.text 239 s->type = STEXT; 240 break; 241 default: 242 werrstr("unexpected flags %#08ux for PE section %s", sect->sh.Characteristics, sect->name); 243 goto bad; 244 } 245 s->p = sect->base; 246 s->np = sect->size; 247 s->size = sect->size; 248 sect->sym = s; 249 if(strcmp(sect->name, ".rsrc") == 0) 250 setpersrc(sect->sym); 251 } 252 253 // load relocations 254 for(i=0; i<obj->nsect; i++) { 255 rsect = &obj->sect[i]; 256 if(rsect->sym == 0 || rsect->sh.NumberOfRelocations == 0) 257 continue; 258 if(rsect->sh.Characteristics&IMAGE_SCN_MEM_DISCARDABLE) 259 continue; 260 if((sect->sh.Characteristics&(IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_CNT_UNINITIALIZED_DATA)) == 0) { 261 // This has been seen for .idata sections, which we 262 // want to ignore. See issues 5106 and 5273. 263 continue; 264 } 265 r = mal(rsect->sh.NumberOfRelocations*sizeof r[0]); 266 Bseek(f, obj->base+rsect->sh.PointerToRelocations, 0); 267 for(j=0; j<rsect->sh.NumberOfRelocations; j++) { 268 rp = &r[j]; 269 if(Bread(f, symbuf, 10) != 10) 270 goto bad; 271 272 uint32 rva, symindex; 273 uint16 type; 274 rva = le32(&symbuf[0]); 275 symindex = le32(&symbuf[4]); 276 type = le16(&symbuf[8]); 277 if(readsym(obj, symindex, &sym) < 0) 278 goto bad; 279 if(sym->sym == nil) { 280 werrstr("reloc of invalid sym %s idx=%d type=%d", sym->name, symindex, sym->type); 281 goto bad; 282 } 283 rp->sym = sym->sym; 284 rp->siz = 4; 285 rp->off = rva; 286 switch(type) { 287 default: 288 diag("%s: unknown relocation type %d;", pn, type); 289 case IMAGE_REL_I386_REL32: 290 case IMAGE_REL_AMD64_REL32: 291 case IMAGE_REL_AMD64_ADDR32: // R_X86_64_PC32 292 case IMAGE_REL_AMD64_ADDR32NB: 293 rp->type = D_PCREL; 294 rp->add = (int32)le32(rsect->base+rp->off); 295 break; 296 case IMAGE_REL_I386_DIR32NB: 297 case IMAGE_REL_I386_DIR32: 298 rp->type = D_ADDR; 299 // load addend from image 300 rp->add = le32(rsect->base+rp->off); 301 break; 302 case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64 303 rp->siz = 8; 304 rp->type = D_ADDR; 305 // load addend from image 306 rp->add = le64(rsect->base+rp->off); 307 break; 308 } 309 // ld -r could generate multiple section symbols for the 310 // same section but with different values, we have to take 311 // that into account 312 if (obj->pesym[symindex].name[0] == '.') 313 rp->add += obj->pesym[symindex].value; 314 } 315 qsort(r, rsect->sh.NumberOfRelocations, sizeof r[0], rbyoff); 316 317 s = rsect->sym; 318 s->r = r; 319 s->nr = rsect->sh.NumberOfRelocations; 320 } 321 322 // enter sub-symbols into symbol table. 323 for(i=0; i<obj->npesym; i++) { 324 if(obj->pesym[i].name == 0) 325 continue; 326 if(obj->pesym[i].name[0] == '.') //skip section 327 continue; 328 if(obj->pesym[i].sectnum > 0) { 329 sect = &obj->sect[obj->pesym[i].sectnum-1]; 330 if(sect->sym == 0) 331 continue; 332 } 333 if(readsym(obj, i, &sym) < 0) 334 goto bad; 335 336 s = sym->sym; 337 if(sym->sectnum == 0) {// extern 338 if(s->type == SDYNIMPORT) 339 s->plt = -2; // flag for dynimport in PE object files. 340 if (s->type == SXREF && sym->value > 0) {// global data 341 s->type = SDATA; 342 s->size = sym->value; 343 } 344 continue; 345 } else if (sym->sectnum > 0) { 346 sect = &obj->sect[sym->sectnum-1]; 347 if(sect->sym == 0) 348 diag("%s: %s sym == 0!", pn, s->name); 349 } else { 350 diag("%s: %s sectnum < 0!", pn, s->name); 351 } 352 353 if(sect == nil) 354 return; 355 356 if(s->outer != S) { 357 if(s->dupok) 358 continue; 359 diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name); 360 errorexit(); 361 } 362 s->sub = sect->sym->sub; 363 sect->sym->sub = s; 364 s->type = sect->sym->type | SSUB; 365 s->value = sym->value; 366 s->size = 4; 367 s->outer = sect->sym; 368 if(sect->sym->type == STEXT) { 369 Prog *p; 370 371 if(s->text != P) 372 diag("%s: duplicate definition of %s", pn, s->name); 373 // build a TEXT instruction with a unique pc 374 // just to make the rest of the linker happy. 375 p = prg(); 376 p->as = ATEXT; 377 p->from.type = D_EXTERN; 378 p->from.sym = s; 379 p->textflag = 7; 380 p->to.type = D_CONST; 381 p->link = nil; 382 p->pc = pc++; 383 s->text = p; 384 } 385 } 386 387 // Sort outer lists by address, adding to textp. 388 // This keeps textp in increasing address order. 389 for(i=0; i<obj->nsect; i++) { 390 s = obj->sect[i].sym; 391 if(s == S) 392 continue; 393 if(s->sub) 394 s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub)); 395 if(s->type == STEXT) { 396 if(etextp) 397 etextp->next = s; 398 else 399 textp = s; 400 etextp = s; 401 for(s = s->sub; s != S; s = s->sub) { 402 etextp->next = s; 403 etextp = s; 404 } 405 } 406 } 407 408 return; 409 bad: 410 diag("%s: malformed pe file: %r", pn); 411 } 412 413 static int 414 map(PeObj *obj, PeSect *sect) 415 { 416 if(sect->base != nil) 417 return 0; 418 419 sect->base = mal(sect->sh.SizeOfRawData); 420 if(sect->sh.PointerToRawData == 0) // .bss doesn't have data in object file 421 return 0; 422 werrstr("short read"); 423 if(Bseek(obj->f, obj->base+sect->sh.PointerToRawData, 0) < 0 || 424 Bread(obj->f, sect->base, sect->sh.SizeOfRawData) != sect->sh.SizeOfRawData) 425 return -1; 426 427 return 0; 428 } 429 430 static int 431 readsym(PeObj *obj, int i, PeSym **y) 432 { 433 Sym *s; 434 PeSym *sym; 435 char *name, *p; 436 437 if(i >= obj->npesym || i < 0) { 438 werrstr("invalid pe symbol index"); 439 return -1; 440 } 441 442 sym = &obj->pesym[i]; 443 *y = sym; 444 445 if(sym->name[0] == '.') // .section 446 name = obj->sect[sym->sectnum-1].sym->name; 447 else { 448 name = sym->name; 449 if(strncmp(name, "__imp_", 6) == 0) 450 name = &name[6]; // __imp_Name => Name 451 if(thechar == '8' && name[0] == '_') 452 name = &name[1]; // _Name => Name 453 } 454 // remove last @XXX 455 p = strchr(name, '@'); 456 if(p) 457 *p = 0; 458 459 switch(sym->type) { 460 default: 461 werrstr("%s: invalid symbol type %d", sym->name, sym->type); 462 return -1; 463 case IMAGE_SYM_DTYPE_FUNCTION: 464 case IMAGE_SYM_DTYPE_NULL: 465 switch(sym->sclass) { 466 case IMAGE_SYM_CLASS_EXTERNAL: //global 467 s = lookup(name, 0); 468 break; 469 case IMAGE_SYM_CLASS_NULL: 470 case IMAGE_SYM_CLASS_STATIC: 471 s = lookup(name, version); 472 break; 473 default: 474 werrstr("%s: invalid symbol binding %d", sym->name, sym->sclass); 475 return -1; 476 } 477 break; 478 } 479 480 if(s != nil && s->type == 0 && !(sym->sclass == IMAGE_SYM_CLASS_STATIC && sym->value == 0)) 481 s->type = SXREF; 482 if(strncmp(sym->name, "__imp_", 6) == 0) 483 s->got = -2; // flag for __imp_ 484 sym->sym = s; 485 486 return 0; 487 }