儲存庫 kStuff 的更動 22
- 時間撮記:
- 2009-1-30 上午06:29:43 (16 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/kLdr/kLdrModMachO.c
r2 r22 55 55 #endif 56 56 57 /** @def KLDRMODMACHO_CHECK_RETURN 58 * Checks that an expression is true and return if it isn't. 59 * This is a debug aid. 60 */ 61 #ifdef KLDRMODMACHO_STRICT2 62 # define KLDRMODMACHO_CHECK_RETURN(expr, rc) kHlpAssertReturn(expr, rc) 63 #else 64 # define KLDRMODMACHO_CHECK_RETURN(expr, rc) do { if (!(expr)) { return (rc); } } while (0) 65 #endif 66 57 67 58 68 /******************************************************************************* … … 121 131 /** The size of the mapped image. */ 122 132 KLDRADDR cbImage; 133 /** The RVA of the Global Offset Table. */ 134 KLDRADDR GotRVA; 135 /** Whether we're creating a global offset table segment. 136 * This dependes on the cputype and image type. */ 137 KBOOL fMakeGot; 123 138 /** When set the sections in the load command segments must be used when 124 139 * mapping or loading the image. */ 125 int fMapUsingLoadCommandSections; 126 140 KBOOL fMapUsingLoadCommandSections; 127 141 /** Pointer to the load commands. (endian converted) */ 128 142 KU8 *pbLoadCommands; … … 178 192 KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, 179 193 KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind); 194 static int kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings, 195 KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, 196 KSIZE cchSymbol, PKLDRADDR puValue, KU32 *pfKind); 180 197 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, KU32 cSyms, 198 const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress, 199 KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); 200 static int kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, 181 201 const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress, 182 202 KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); … … 185 205 static int kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect, 186 206 macho_nlist_32_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress); 207 static int kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect, 208 macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress); 209 210 static int kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress); 187 211 188 212 /*static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); … … 227 251 228 252 /** 229 * Separate function for reading creating the PEmodule instance to253 * Separate function for reading creating the Mach-O module instance to 230 254 * simplify cleanup on failure. 231 255 */ … … 245 269 KSIZE cchFilename; 246 270 KSIZE cb; 271 KBOOL fMakeGot; 247 272 int rc; 248 273 *ppModMachO = NULL; 274 275 kHlpAssert(&s.Hdr32.magic == &s.Hdr64.magic); 276 kHlpAssert(&s.Hdr32.flags == &s.Hdr64.flags); 249 277 250 278 /* … … 254 282 if (rc) 255 283 return rc; 256 if (s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE) 284 if ( s.Hdr32.magic != IMAGE_MACHO32_SIGNATURE 285 && s.Hdr32.magic != IMAGE_MACHO64_SIGNATURE 286 ) 257 287 { 258 288 if ( s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE 259 289 || s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE_OE) 260 290 return KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED; 261 if (s.Hdr32.magic == IMAGE_MACHO64_SIGNATURE)262 return KLDR_ERR_MACHO_64BIT_NOT_SUPPORTED;263 291 return KLDR_ERR_UNKNOWN_FORMAT; 264 292 } … … 272 300 { 273 301 case CPU_TYPE_X86: 302 fMakeGot = K_FALSE; 303 break; 274 304 case CPU_TYPE_X86_64: 305 fMakeGot = s.Hdr32.filetype == MH_OBJECT; 275 306 break; 276 307 default: … … 297 328 return rc; 298 329 } 330 cSegments += fMakeGot; 299 331 300 332 … … 361 393 pMod->enmArch = KCPUARCH_AMD64; 362 394 pMod->enmEndian = KLDRENDIAN_LITTLE; 363 switch (s.Hdr32.cpusubtype )395 switch (s.Hdr32.cpusubtype & ~CPU_SUBTYPE_MASK) 364 396 { 365 397 case CPU_SUBTYPE_X86_64_ALL: pMod->enmCpu = KCPU_AMD64_BLEND; break; … … 394 426 pModMachO->LinkAddress = 0; 395 427 pModMachO->cbImage = 0; 396 pModMachO->fMapUsingLoadCommandSections = 0; 428 pModMachO->GotRVA = NIL_KLDRADDR; 429 pModMachO->fMakeGot = fMakeGot; 430 pModMachO->fMapUsingLoadCommandSections = K_FALSE; 397 431 pModMachO->offSymbols = 0; 398 432 pModMachO->cSymbols = 0; … … 577 611 case S_LAZY_SYMBOL_POINTERS: 578 612 case S_SYMBOL_STUBS: 613 return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; 579 614 case S_MOD_INIT_FUNC_POINTERS: 615 return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; 580 616 case S_MOD_TERM_FUNC_POINTERS: 581 return KLDR_ERR_MACHO_UNSUPPORTED_ SECTION;617 return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; 582 618 583 619 default: … … 625 661 || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) 626 662 { 627 #if 0 /** @todo This 663 #if 0 /** @todo This doesn't work because of BSS. */ 628 664 /* verify that the linker/assembler has ordered sections correctly. */ 629 665 section_32_t *pCur = (pSect - 2); … … 653 689 } 654 690 655 /*case LC_SEGMENT_64: 656 copy 32-bit code 691 case LC_SEGMENT_64: 692 { 693 section_64_t *pSect; 694 section_64_t *pFirstSect; 695 KU32 cSectionsLeft; 696 697 /* convert and verify*/ 698 if (u.pLoadCmd->cmdsize < sizeof(segment_command_64_t)) 699 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 700 if ( pHdr->magic != IMAGE_MACHO64_SIGNATURE_OE 701 && pHdr->magic != IMAGE_MACHO64_SIGNATURE) 702 return KLDR_ERR_MACHO_BIT_MIX; 703 if (fConvertEndian) 704 { 705 u.pSeg64->vmaddr = K_E2E_U64(u.pSeg64->vmaddr); 706 u.pSeg64->vmsize = K_E2E_U64(u.pSeg64->vmsize); 707 u.pSeg64->fileoff = K_E2E_U64(u.pSeg64->fileoff); 708 u.pSeg64->filesize = K_E2E_U64(u.pSeg64->filesize); 709 u.pSeg64->maxprot = K_E2E_U32(u.pSeg64->maxprot); 710 u.pSeg64->initprot = K_E2E_U32(u.pSeg64->initprot); 711 u.pSeg64->nsects = K_E2E_U32(u.pSeg64->nsects); 712 u.pSeg64->flags = K_E2E_U32(u.pSeg64->flags); 713 } 714 715 if ( u.pSeg64->filesize 716 && ( u.pSeg64->fileoff > cbFile 717 || u.pSeg64->fileoff + u.pSeg64->filesize > cbFile)) 718 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 719 if (!u.pSeg64->filesize && u.pSeg64->fileoff) 720 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 721 if (u.pSeg64->vmsize < u.pSeg64->filesize) 722 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 723 if ((u.pSeg64->maxprot & u.pSeg64->initprot) != u.pSeg64->initprot) 724 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 725 if (u.pSeg64->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1)) 726 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 727 if (u.pSeg64->nsects * sizeof(section_64_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_64_t)) 728 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 729 if ( pHdr->filetype == MH_OBJECT 730 && cSegmentCommands > 0) 731 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 732 cSegmentCommands++; 733 734 /* 735 * convert, validate and parse the sections. 736 */ 737 cSectionsLeft = u.pSeg64->nsects; 738 pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1); 739 while (cSectionsLeft-- > 0) 740 { 741 int fFileBits; 742 743 if (fConvertEndian) 744 { 745 pSect->addr = K_E2E_U64(pSect->addr); 746 pSect->size = K_E2E_U64(pSect->size); 747 pSect->offset = K_E2E_U32(pSect->offset); 748 pSect->align = K_E2E_U32(pSect->align); 749 pSect->reloff = K_E2E_U32(pSect->reloff); 750 pSect->nreloc = K_E2E_U32(pSect->nreloc); 751 pSect->flags = K_E2E_U32(pSect->flags); 752 pSect->reserved1 = K_E2E_U32(pSect->reserved1); 753 pSect->reserved2 = K_E2E_U32(pSect->reserved2); 754 } 755 756 /* validate */ 757 switch (pSect->flags & SECTION_TYPE) 758 { 759 case S_ZEROFILL: 760 if (pSect->reserved1 || pSect->reserved2) 761 return KLDR_ERR_MACHO_BAD_SECTION; 762 fFileBits = 0; 763 break; 764 case S_REGULAR: 765 case S_CSTRING_LITERALS: 766 case S_COALESCED: 767 case S_4BYTE_LITERALS: 768 case S_8BYTE_LITERALS: 769 case S_16BYTE_LITERALS: 770 if (pSect->reserved1 || pSect->reserved2) 771 return KLDR_ERR_MACHO_BAD_SECTION; 772 fFileBits = 1; 773 break; 774 775 case S_LITERAL_POINTERS: 776 case S_INTERPOSING: 777 case S_GB_ZEROFILL: 778 case S_NON_LAZY_SYMBOL_POINTERS: 779 case S_LAZY_SYMBOL_POINTERS: 780 case S_SYMBOL_STUBS: 781 return KLDR_ERR_MACHO_UNSUPPORTED_SECTION; 782 #if 1 /** @todo this requires a query API or flag... */ 783 case S_MOD_INIT_FUNC_POINTERS: 784 return KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION; 785 case S_MOD_TERM_FUNC_POINTERS: 786 return KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION; 787 #else 788 case S_MOD_INIT_FUNC_POINTERS: 789 case S_MOD_TERM_FUNC_POINTERS: 790 fFileBits = 1; 791 break; /* ignored */ 792 #endif 793 794 default: 795 return KLDR_ERR_MACHO_UNKNOWN_SECTION; 796 } 797 if (pSect->flags & ~( S_ATTR_PURE_INSTRUCTIONS | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS 798 | S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT | S_ATTR_SELF_MODIFYING_CODE 799 | S_ATTR_DEBUG | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_EXT_RELOC 800 | S_ATTR_LOC_RELOC | SECTION_TYPE)) 801 return KLDR_ERR_MACHO_BAD_SECTION; 802 if ( pSect->addr - u.pSeg64->vmaddr > u.pSeg64->vmsize 803 || pSect->addr - u.pSeg64->vmaddr + pSect->size > u.pSeg64->vmsize) 804 return KLDR_ERR_MACHO_BAD_SECTION; 805 if ( pSect->align >= 31 806 || (((1 << pSect->align) - 1) & pSect->addr) 807 || (((1 << pSect->align) - 1) & u.pSeg64->vmaddr)) 808 return KLDR_ERR_MACHO_BAD_SECTION; 809 if ( fFileBits 810 && ( pSect->offset > cbFile 811 || (KU64)pSect->offset + pSect->size > cbFile)) 812 return KLDR_ERR_MACHO_BAD_SECTION; 813 if (!fFileBits && pSect->offset) 814 return KLDR_ERR_MACHO_BAD_SECTION; 815 if (!pSect->nreloc && pSect->reloff) 816 return KLDR_ERR_MACHO_BAD_SECTION; 817 if ( pSect->nreloc 818 && ( pSect->reloff > cbFile 819 || (KU64)pSect->reloff + (KLDRFOFF)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile) 820 return KLDR_ERR_MACHO_BAD_SECTION; 821 822 823 /* count segments and strings */ 824 switch (pHdr->filetype) 825 { 826 case MH_OBJECT: 827 { 828 cSections++; 829 830 /* Don't load debug symbols. (test this) */ 831 if (pSect->flags & S_ATTR_DEBUG) 832 break; 833 834 /* a new segment? */ 835 if ( !cSegments 836 || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) 837 { 838 #if 0 /** @todo This doesn't work because of BSS. */ 839 /* verify that the linker/assembler has ordered sections correctly. */ 840 section_64_t *pCur = (pSect - 2); 841 while ((KUPTR)pCur >= (KUPTR)pFirstSect) 842 { 843 if (!kHlpStrNComp(pCur->segname, pSect->segname, sizeof(pSect->segname))) 844 return KLDR_ERR_MACHO_BAD_SECTION_ORDER; 845 pCur--; 846 } 847 #endif 848 849 /* ok. count it and the string. */ 850 cSegments++; 851 cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; 852 } 853 break; 854 } 855 856 default: 857 return KERR_INVALID_PARAMETER; 858 } 859 860 /* next */ 861 pSect++; 862 } 657 863 break; 658 */ 864 } /* LC_SEGMENT_64 */ 865 659 866 660 867 case LC_SYMTAB: … … 732 939 break; 733 940 734 case LC_SEGMENT_64:735 941 case LC_LOADFVMLIB: 736 942 case LC_IDFVMLIB: … … 918 1124 919 1125 pSeg[-1].cbFile = pSeg[-1].offFile = -1; 920 pModMachO->fMapUsingLoadCommandSections = 1; 1126 pModMachO->fMapUsingLoadCommandSections = K_TRUE; 1127 } 1128 } 1129 pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size; 1130 1131 /** @todo update the protection... */ 1132 } 1133 pSectExtra++; 1134 break; 1135 } 1136 1137 default: 1138 return KERR_INVALID_PARAMETER; 1139 } 1140 1141 /* next */ 1142 pSect++; 1143 } 1144 break; 1145 } 1146 1147 case LC_SEGMENT_64: 1148 { 1149 section_64_t *pSect; 1150 section_64_t *pFirstSect; 1151 KU32 cSectionsLeft; 1152 1153 pModMachO->LinkAddress = u.pSeg64->vmaddr; 1154 1155 /* 1156 * convert, validate and parse the sections. 1157 */ 1158 cSectionsLeft = u.pSeg64->nsects; 1159 pFirstSect = pSect = (section_64_t *)(u.pSeg64 + 1); 1160 while (cSectionsLeft-- > 0) 1161 { 1162 switch (pModMachO->Hdr.filetype) 1163 { 1164 case MH_OBJECT: 1165 { 1166 /* Section data extract. */ 1167 pSectExtra->cb = pSect->size; 1168 pSectExtra->RVA = pSect->addr; 1169 pSectExtra->LinkAddress = pSect->addr; 1170 pSectExtra->offFile = pSect->offset ? pSect->offset : -1; 1171 pSectExtra->cFixups = pSect->nreloc; 1172 pSectExtra->paFixups = NULL; 1173 pSectExtra->offFixups = pSect->nreloc ? pSect->reloff : -1; 1174 pSectExtra->fFlags = pSect->flags; 1175 pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; 1176 pSectExtra->pvMachoSection = pSect; 1177 1178 /* Don't load debug symbols. (test this!) */ 1179 if (pSect->flags & S_ATTR_DEBUG) 1180 { 1181 pSectExtra++; 1182 /** @todo */ 1183 break; 1184 } 1185 1186 if ( fFirstSegment 1187 || kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) 1188 { 1189 /* close the previous segment */ 1190 if (pSegExtra != &pModMachO->aSegments[0]) 1191 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 1192 1193 /* new segment. */ 1194 pSeg->pvUser = NULL; 1195 pSeg->pchName = pbStringPool; 1196 pSeg->cchName = (KU32)kHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname)); 1197 kHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName); 1198 pbStringPool += pSeg->cchName; 1199 *pbStringPool++ = '\0'; 1200 pSeg->SelFlat = 0; 1201 pSeg->Sel16bit = 0; 1202 pSeg->fFlags = 0; 1203 pSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ 1204 pSeg->cb = pSect->size; 1205 pSeg->Alignment = (1 << pSect->align); 1206 pSeg->LinkAddress = pSect->addr; 1207 pSeg->offFile = pSect->offset ? pSect->offset : -1; 1208 pSeg->cbFile = pSect->offset ? pSect->size : -1; 1209 pSeg->RVA = pSect->addr - pModMachO->LinkAddress; 1210 pSeg->cbMapped = 0; 1211 pSeg->MapAddress = 0; 1212 1213 pSegExtra->cSections = 0; 1214 pSegExtra->paSections = pSectExtra; 1215 1216 pSeg++; 1217 pSegExtra++; 1218 fFirstSegment = 0; 1219 } 1220 else 1221 { 1222 /* update exiting segment */ 1223 if (pSeg[-1].Alignment < (1 << pSect->align)) 1224 pSeg[-1].Alignment = (1 << pSect->align); 1225 if (pSect->addr < pSeg[-1].LinkAddress) 1226 return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */ 1227 1228 /* If there are file bits, ensure they are in the current flow. 1229 (yes, we are very very careful here, I know.) */ 1230 if ( pSect->offset 1231 && pSeg[-1].cbFile == pSeg[-1].cb) 1232 { 1233 int fOk = pSeg[-1].offFile + (pSect->addr - pSeg[-1].LinkAddress) == pSect->offset 1234 && pSect[-1].offset 1235 && pSeg[-1].offFile + pSeg[-1].cbFile == pSect[-1].offset + pSect[-1].size; 1236 /* more checks? */ 1237 if (fOk) 1238 pSeg[-1].cbFile = (KLDRFOFF)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size; 1239 else 1240 { 1241 1242 pSeg[-1].cbFile = pSeg[-1].offFile = -1; 1243 pModMachO->fMapUsingLoadCommandSections = K_TRUE; 921 1244 } 922 1245 } … … 963 1286 964 1287 /* 1288 * Make the GOT segment if necessary. 1289 */ 1290 if (pModMachO->fMakeGot) 1291 { 1292 KSIZE cbPtr = ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1293 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1294 ? sizeof(KU32) 1295 : sizeof(KU64); 1296 1297 if (pSeg != &pModMachO->pMod->aSegments[0]) 1298 pModMachO->GotRVA = pSeg[-1].RVA + KLDR_ALIGN_ADDR(pSeg[-1].cb, pSeg[-1].Alignment); 1299 else 1300 pModMachO->GotRVA = 0; 1301 1302 pSeg->pvUser = NULL; 1303 pSeg->pchName = "GOT"; 1304 pSeg->cchName = 3; 1305 pSeg->SelFlat = 0; 1306 pSeg->Sel16bit = 0; 1307 pSeg->fFlags = 0; 1308 pSeg->enmProt = KPROT_READONLY; 1309 pSeg->cb = cbPtr * pModMachO->cSymbols; 1310 pSeg->Alignment = 64; 1311 pSeg->LinkAddress = pModMachO->LinkAddress + pModMachO->GotRVA; 1312 pSeg->offFile = -1; 1313 pSeg->cbFile = -1; 1314 pSeg->RVA = pModMachO->GotRVA; 1315 pSeg->cbMapped = 0; 1316 pSeg->MapAddress = 0; 1317 1318 pSegExtra->cSections = 0; 1319 pSegExtra->paSections = NULL; 1320 } 1321 1322 /* 965 1323 * Adjust mapping addresses calculating the image size. 966 1324 */ … … 987 1345 } 988 1346 } 1347 989 1348 990 1349 return 0; … … 1070 1429 * Refuse segmented requests for now. 1071 1430 */ 1072 if (pfKind1073 && (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) != KLDRSYMKIND_REQ_FLAT)1074 return KLDR_ERR_TODO;1431 KLDRMODMACHO_CHECK_RETURN( !pfKind 1432 || (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) == KLDRSYMKIND_REQ_FLAT, 1433 KLDR_ERR_TODO); 1075 1434 1076 1435 /* … … 1088 1447 cchSymbol, puValue, pfKind); 1089 1448 else 1090 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */ 1091 /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1449 rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1092 1450 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 1093 cchSymbol, puValue, pfKind);*/ 1094 1451 cchSymbol, puValue, pfKind); 1095 1452 } 1096 1453 } … … 1100 1457 return rc; 1101 1458 } 1102 1103 1459 1104 1460 … … 1222 1578 /** @todo implement indirect and prebound symbols. */ 1223 1579 default: 1224 KLDRMODMACHO_ASSERT(0); 1225 return KLDR_ERR_TODO; 1580 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1581 } 1582 1583 return 0; 1584 } 1585 1586 1587 /** 1588 * Lookup a symbol in a 64-bit symbol table. 1589 * 1590 * @returns See kLdrModQuerySymbol. 1591 * @param pModMachO 1592 * @param paSyms Pointer to the symbol table. 1593 * @param cSyms Number of symbols in the table. 1594 * @param pchStrings Pointer to the string table. 1595 * @param cchStrings Size of the string table. 1596 * @param BaseAddress Adjusted base address, see kLdrModQuerySymbol. 1597 * @param iSymbol See kLdrModQuerySymbol. 1598 * @param pchSymbol See kLdrModQuerySymbol. 1599 * @param cchSymbol See kLdrModQuerySymbol. 1600 * @param puValue See kLdrModQuerySymbol. 1601 * @param pfKind See kLdrModQuerySymbol. 1602 */ 1603 static int kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, const char *pchStrings, 1604 KU32 cchStrings, KLDRADDR BaseAddress, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol, 1605 PKLDRADDR puValue, KU32 *pfKind) 1606 { 1607 /* 1608 * Find a valid symbol matching the search criteria. 1609 */ 1610 if (iSymbol == NIL_KLDRMOD_SYM_ORDINAL) 1611 { 1612 /* simplify validation. */ 1613 if (cchStrings <= cchSymbol) 1614 return KLDR_ERR_SYMBOL_NOT_FOUND; 1615 cchStrings -= cchSymbol; 1616 1617 /* external symbols are usually at the end, so search the other way. */ 1618 for (iSymbol = cSyms - 1; iSymbol != KU32_MAX; iSymbol--) 1619 { 1620 const char *psz; 1621 1622 /* Skip irrellevant and non-public symbols. */ 1623 if (paSyms[iSymbol].n_type & MACHO_N_STAB) 1624 continue; 1625 if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1626 continue; 1627 if (!(paSyms[iSymbol].n_type & MACHO_N_EXT)) /*??*/ 1628 continue; 1629 if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/ 1630 continue; 1631 1632 /* get name */ 1633 if (!paSyms[iSymbol].n_un.n_strx) 1634 continue; 1635 if ((KU32)paSyms[iSymbol].n_un.n_strx >= cchStrings) 1636 continue; 1637 psz = &pchStrings[paSyms[iSymbol].n_un.n_strx]; 1638 if (psz[cchSymbol]) 1639 continue; 1640 if (kHlpMemComp(psz, pchSymbol, cchSymbol)) 1641 continue; 1642 1643 /* match! */ 1644 break; 1645 } 1646 if (iSymbol == KU32_MAX) 1647 return KLDR_ERR_SYMBOL_NOT_FOUND; 1648 } 1649 else 1650 { 1651 if (iSymbol >= cSyms) 1652 return KLDR_ERR_SYMBOL_NOT_FOUND; 1653 if (paSyms[iSymbol].n_type & MACHO_N_STAB) 1654 return KLDR_ERR_SYMBOL_NOT_FOUND; 1655 if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1656 return KLDR_ERR_SYMBOL_NOT_FOUND; 1657 } 1658 1659 /* 1660 * Calc the return values. 1661 */ 1662 if (pfKind) 1663 { 1664 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1665 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1666 *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE; 1667 else 1668 *pfKind = KLDRSYMKIND_64BIT | KLDRSYMKIND_NO_TYPE; 1669 if (paSyms[iSymbol].n_desc & N_WEAK_DEF) 1670 *pfKind |= KLDRSYMKIND_WEAK; 1671 } 1672 1673 switch (paSyms[iSymbol].n_type & MACHO_N_TYPE) 1674 { 1675 case MACHO_N_SECT: 1676 { 1677 PKLDRMODMACHOSECT pSect; 1678 KLDRADDR RVA; 1679 if ((KU32)(paSyms[iSymbol].n_sect - 1) >= pModMachO->cSections) 1680 return KLDR_ERR_MACHO_BAD_SYMBOL; 1681 pSect = &pModMachO->paSections[paSyms[iSymbol].n_sect - 1]; 1682 1683 RVA = paSyms[iSymbol].n_value - pModMachO->LinkAddress; 1684 if (RVA - pSect->RVA >= pSect->cb) 1685 return KLDR_ERR_MACHO_BAD_SYMBOL; 1686 if (puValue) 1687 *puValue = RVA + BaseAddress; 1688 1689 if ( pfKind 1690 && (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))) 1691 *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE; 1692 break; 1693 } 1694 1695 case MACHO_N_ABS: 1696 if (puValue) 1697 *puValue = paSyms[iSymbol].n_value; 1698 /*if (pfKind) 1699 pfKind |= KLDRSYMKIND_ABS;*/ 1700 break; 1701 1702 case MACHO_N_PBUD: 1703 case MACHO_N_INDR: 1704 /** @todo implement indirect and prebound symbols. */ 1705 default: 1706 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1226 1707 } 1227 1708 … … 1258 1739 fFlags, pfnCallback, pvUser); 1259 1740 else 1260 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */1261 /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,1262 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, pfnCallback, pvUser);*/1741 rc = kldrModMachODoEnumSymbols64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1742 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, 1743 fFlags, pfnCallback, pvUser); 1263 1744 } 1264 1745 } 1265 1746 else 1266 rc = KLDR_ERR_TODO;1747 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1267 1748 1268 1749 return rc; … … 1288 1769 KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) 1289 1770 { 1290 const KU32 fKindBase = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE1291 1292 1771 const KU32 fKindBase = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1772 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 1773 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT; 1293 1774 KU32 iSym; 1294 1775 int rc; … … 1367 1848 /** @todo implement indirect and prebound symbols. */ 1368 1849 default: 1369 KLDRMODMACHO_ASSERT(0); 1370 return KLDR_ERR_TODO; 1850 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1851 } 1852 1853 /* 1854 * Do callback. 1855 */ 1856 rc = pfnCallback(pModMachO->pMod, iSym, psz, cch, NULL, uValue, fKind, pvUser); 1857 if (rc) 1858 return rc; 1859 } 1860 return 0; 1861 } 1862 1863 1864 /** 1865 * Enum a 64-bit symbol table. 1866 * 1867 * @returns See kLdrModQuerySymbol. 1868 * @param pModMachO 1869 * @param paSyms Pointer to the symbol table. 1870 * @param cSyms Number of symbols in the table. 1871 * @param pchStrings Pointer to the string table. 1872 * @param cchStrings Size of the string table. 1873 * @param BaseAddress Adjusted base address, see kLdrModEnumSymbols. 1874 * @param fFlags See kLdrModEnumSymbols. 1875 * @param pfnCallback See kLdrModEnumSymbols. 1876 * @param pvUser See kLdrModEnumSymbols. 1877 */ 1878 static int kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_nlist_64_t *paSyms, KU32 cSyms, 1879 const char *pchStrings, KU32 cchStrings, KLDRADDR BaseAddress, 1880 KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) 1881 { 1882 const KU32 fKindBase = pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE 1883 || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE 1884 ? KLDRSYMKIND_64BIT : KLDRSYMKIND_32BIT; 1885 KU32 iSym; 1886 int rc; 1887 1888 /* 1889 * Iterate the symbol table. 1890 */ 1891 for (iSym = 0; iSym < cSyms; iSym++) 1892 { 1893 KU32 fKind; 1894 KLDRADDR uValue; 1895 const char *psz; 1896 KSIZE cch; 1897 1898 /* Skip debug symbols and undefined symbols. */ 1899 if (paSyms[iSym].n_type & MACHO_N_STAB) 1900 continue; 1901 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1902 continue; 1903 1904 /* Skip non-public symbols unless they are requested explicitly. */ 1905 if (!(fFlags & KLDRMOD_ENUM_SYMS_FLAGS_ALL)) 1906 { 1907 if (!(paSyms[iSym].n_type & MACHO_N_EXT)) /*??*/ 1908 continue; 1909 if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/ 1910 continue; 1911 if (!paSyms[iSym].n_un.n_strx) 1912 continue; 1913 } 1914 1915 /* 1916 * Gather symbol info 1917 */ 1918 1919 /* name */ 1920 if ((KU32)paSyms[iSym].n_un.n_strx >= cchStrings) 1921 return KLDR_ERR_MACHO_BAD_SYMBOL; 1922 psz = &pchStrings[paSyms[iSym].n_un.n_strx]; 1923 cch = kHlpStrLen(psz); 1924 if (!cch) 1925 psz = NULL; 1926 1927 /* kind & value */ 1928 fKind = fKindBase; 1929 if (paSyms[iSym].n_desc & N_WEAK_DEF) 1930 fKind |= KLDRSYMKIND_WEAK; 1931 switch (paSyms[iSym].n_type & MACHO_N_TYPE) 1932 { 1933 case MACHO_N_SECT: 1934 { 1935 PKLDRMODMACHOSECT pSect; 1936 if ((KU32)(paSyms[iSym].n_sect - 1) >= pModMachO->cSections) 1937 return KLDR_ERR_MACHO_BAD_SYMBOL; 1938 pSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1]; 1939 1940 uValue = paSyms[iSym].n_value - pModMachO->LinkAddress; 1941 if (uValue - pSect->RVA >= pSect->cb) 1942 return KLDR_ERR_MACHO_BAD_SYMBOL; 1943 uValue += BaseAddress; 1944 1945 if (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)) 1946 fKind |= KLDRSYMKIND_CODE; 1947 else 1948 fKind |= KLDRSYMKIND_NO_TYPE; 1949 break; 1950 } 1951 1952 case MACHO_N_ABS: 1953 uValue = paSyms[iSym].n_value; 1954 fKind |= KLDRSYMKIND_NO_TYPE /*KLDRSYMKIND_ABS*/; 1955 break; 1956 1957 case MACHO_N_PBUD: 1958 case MACHO_N_INDR: 1959 /** @todo implement indirect and prebound symbols. */ 1960 default: 1961 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1371 1962 } 1372 1963 … … 1574 2165 /* try do the prepare */ 1575 2166 if (pModMachO->fMapUsingLoadCommandSections) 1576 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */2167 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 1577 2168 else 1578 2169 { … … 1613 2204 */ 1614 2205 if (pModMachO->fMapUsingLoadCommandSections) 1615 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */2206 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 1616 2207 else 1617 2208 { … … 1684 2275 */ 1685 2276 if (pModMachO->fMapUsingLoadCommandSections) 1686 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */2277 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 1687 2278 else 1688 2279 { … … 1754 2345 1755 2346 /** @todo Implement N_REF_TO_WEAK. */ 1756 if (paSyms[iSym].n_desc & N_REF_TO_WEAK) 1757 return KLDR_ERR_TODO; 2347 KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO); 1758 2348 1759 2349 /* Get the symbol name and try resolve it. */ … … 1805 2395 1806 2396 /** @todo Implement N_REF_TO_WEAK. */ 1807 if (paSyms[iSym].n_desc & N_REF_TO_WEAK) 1808 return KLDR_ERR_TODO; 1809 1810 /* Get the symbol name and try resolve it. */ 2397 KLDRMODMACHO_CHECK_RETURN(!(paSyms[iSym].n_desc & N_REF_TO_WEAK), KLDR_ERR_TODO); 2398 2399 /* Get the symbol name and try resolve it. */ 1811 2400 if (paSyms[iSym].n_un.n_strx >= pModMachO->cchStrings) 1812 2401 return KLDR_ERR_MACHO_BAD_SYMBOL; … … 1898 2487 (macho_nlist_32_t *)pModMachO->pvaSymbols, 1899 2488 pModMachO->cSymbols, NewBaseAddress); 2489 else if ( pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE 2490 && pModMachO->Hdr.cputype == CPU_TYPE_X86_64) 2491 rc = kldrModMachOFixupSectionAMD64(pModMachO, pbSectBits, pSect, 2492 (macho_nlist_64_t *)pModMachO->pvaSymbols, 2493 pModMachO->cSymbols, NewBaseAddress); 1900 2494 else 1901 rc = KLDR_ERR_TODO; /* save space for now. */2495 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 1902 2496 if (rc) 1903 2497 break; … … 2013 2607 case MACHO_N_INDR: 2014 2608 case MACHO_N_PBUD: 2015 return KLDR_ERR_TODO;2609 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 2016 2610 default: 2017 return KLDR_ERR_MACHO_BAD_SYMBOL;2611 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL); 2018 2612 } 2019 2613 } … … 2113 2707 2114 2708 /** 2709 * Applies AMD64 fixups to a section. 2710 * 2711 * @returns 0 on success, non-zero kLdr status code on failure. 2712 * @param pModMachO The Mach-O module interpreter instance. 2713 * @param pbSectBits Pointer to the section bits. 2714 * @param pFixupSect The section being fixed up. 2715 * @param NewBaseAddress The new base image address. 2716 */ 2717 static int kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBits, PKLDRMODMACHOSECT pFixupSect, 2718 macho_nlist_64_t *paSyms, KU32 cSyms, KLDRADDR NewBaseAddress) 2719 { 2720 const macho_relocation_info_t *paFixups = pFixupSect->paFixups; 2721 const KU32 cFixups = pFixupSect->cFixups; 2722 KSIZE cbSectBits = (KSIZE)pFixupSect->cb; 2723 const KU8 *pbSectVirginBits; 2724 KU32 iFixup; 2725 KLDRPU uFixVirgin; 2726 KLDRPU uFix; 2727 KLDRADDR SymAddr; 2728 int rc; 2729 2730 /* 2731 * Find the virgin bits. 2732 */ 2733 if (pFixupSect->offFile != -1) 2734 { 2735 rc = kldrModMachOMapVirginBits(pModMachO); 2736 if (rc) 2737 return rc; 2738 pbSectVirginBits = (const KU8 *)pModMachO->pvBits + pFixupSect->offFile; 2739 } 2740 else 2741 pbSectVirginBits = NULL; 2742 2743 /* 2744 * Iterate the fixups and apply them. 2745 */ 2746 for (iFixup = 0; iFixup < cFixups; iFixup++) 2747 { 2748 union 2749 { 2750 macho_relocation_info_t r; 2751 scattered_relocation_info_t s; 2752 } Fixup; 2753 Fixup.r = paFixups[iFixup]; 2754 2755 /* AMD64 doesn't use scattered fixups. */ 2756 KLDRMODMACHO_CHECK_RETURN(!(Fixup.r.r_address & R_SCATTERED), KLDR_ERR_BAD_FIXUP); 2757 2758 /* sanity */ 2759 KLDRMODMACHO_CHECK_RETURN((KU32)Fixup.r.r_address < cbSectBits, KLDR_ERR_BAD_FIXUP); 2760 2761 /* calc fixup addresses. */ 2762 uFix.pv = pbSectBits + Fixup.r.r_address; 2763 uFixVirgin.pv = pbSectVirginBits ? (KU8 *)pbSectVirginBits + Fixup.r.r_address : 0; 2764 2765 /* 2766 * Calc the symbol value. 2767 */ 2768 /* Calc the linked symbol address / addend. */ 2769 switch (Fixup.r.r_length) 2770 { 2771 /** @todo Deal with unaligned accesses on non x86 platforms. */ 2772 case 2: SymAddr = *uFixVirgin.pi32; break; 2773 case 3: SymAddr = *uFixVirgin.pi64; break; 2774 default: 2775 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP); 2776 } 2777 if (Fixup.r.r_pcrel) 2778 SymAddr += Fixup.r.r_address + pFixupSect->LinkAddress; 2779 2780 /* Add symbol / section address. */ 2781 if (Fixup.r.r_extern) 2782 { 2783 const macho_nlist_64_t *pSym; 2784 2785 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum < cSyms, KLDR_ERR_BAD_FIXUP); 2786 pSym = &paSyms[Fixup.r.r_symbolnum]; 2787 KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP); 2788 2789 switch (Fixup.r.r_type) 2790 { 2791 /* GOT references just needs to have their symbol verified. 2792 Later, we'll optimize GOT building here using a parallel sym->got array. */ 2793 case X86_64_RELOC_GOT_LOAD: 2794 case X86_64_RELOC_GOT: 2795 switch (pSym->n_type & MACHO_N_TYPE) 2796 { 2797 case MACHO_N_SECT: 2798 case MACHO_N_UNDF: 2799 case MACHO_N_ABS: 2800 break; 2801 case MACHO_N_INDR: 2802 case MACHO_N_PBUD: 2803 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 2804 default: 2805 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL); 2806 } 2807 SymAddr = sizeof(KU64) * Fixup.r.r_symbolnum + pModMachO->GotRVA + NewBaseAddress; 2808 break; 2809 2810 /* Verify the r_pcrel field for signed fixups on the way into the default case. */ 2811 case X86_64_RELOC_BRANCH: 2812 case X86_64_RELOC_SIGNED: 2813 case X86_64_RELOC_SIGNED_1: 2814 case X86_64_RELOC_SIGNED_2: 2815 case X86_64_RELOC_SIGNED_4: 2816 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP); 2817 default: 2818 { 2819 /* Adjust with fixup specific addend and vierfy unsigned/r_pcrel. */ 2820 switch (Fixup.r.r_type) 2821 { 2822 case X86_64_RELOC_UNSIGNED: 2823 KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP); 2824 break; 2825 case X86_64_RELOC_SIGNED: 2826 break; 2827 case X86_64_RELOC_BRANCH: 2828 switch (Fixup.r.r_length) 2829 { 2830 case 0: SymAddr -= 1; break; 2831 case 1: SymAddr -= 2; break; 2832 case 2: SymAddr -= 4; break; 2833 case 3: SymAddr -= 8; break; 2834 } 2835 break; 2836 case X86_64_RELOC_SIGNED_1: SymAddr -= 1; break; 2837 case X86_64_RELOC_SIGNED_2: SymAddr -= 2; break; 2838 case X86_64_RELOC_SIGNED_4: SymAddr -= 4; break; 2839 default: 2840 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP); 2841 } 2842 2843 switch (pSym->n_type & MACHO_N_TYPE) 2844 { 2845 case MACHO_N_SECT: 2846 { 2847 PKLDRMODMACHOSECT pSymSect; 2848 KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL); 2849 pSymSect = &pModMachO->paSections[pSym->n_sect - 1]; 2850 SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 2851 break; 2852 } 2853 2854 case MACHO_N_UNDF: 2855 case MACHO_N_ABS: 2856 SymAddr += pSym->n_value; 2857 break; 2858 2859 case MACHO_N_INDR: 2860 case MACHO_N_PBUD: 2861 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 2862 default: 2863 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL); 2864 } 2865 break; 2866 } 2867 2868 /* 2869 * This is a weird customer, it will always be follows by an UNSIGNED fixup. 2870 */ 2871 case X86_64_RELOC_SUBTRACTOR: 2872 { 2873 macho_relocation_info_t Fixup2; 2874 2875 /* Deal with the SUBTRACT symbol first, by subtracting it from SymAddr. */ 2876 switch (pSym->n_type & MACHO_N_TYPE) 2877 { 2878 case MACHO_N_SECT: 2879 { 2880 PKLDRMODMACHOSECT pSymSect; 2881 KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL); 2882 pSymSect = &pModMachO->paSections[pSym->n_sect - 1]; 2883 SymAddr -= pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 2884 break; 2885 } 2886 2887 case MACHO_N_UNDF: 2888 case MACHO_N_ABS: 2889 SymAddr -= pSym->n_value; 2890 break; 2891 2892 case MACHO_N_INDR: 2893 case MACHO_N_PBUD: 2894 KLDRMODMACHO_CHECK_RETURN(0,KLDR_ERR_TODO); 2895 default: 2896 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL); 2897 } 2898 2899 /* Load the 2nd fixup, check sanity. */ 2900 iFixup++; 2901 KLDRMODMACHO_CHECK_RETURN(!Fixup.r.r_pcrel && iFixup < cFixups, KLDR_ERR_BAD_FIXUP); 2902 Fixup2 = paFixups[iFixup]; 2903 KLDRMODMACHO_CHECK_RETURN( Fixup2.r_address == Fixup.r.r_address 2904 && Fixup2.r_length == Fixup.r.r_length 2905 && Fixup2.r_type == X86_64_RELOC_UNSIGNED 2906 && !Fixup2.r_pcrel 2907 && Fixup2.r_extern /*??*/ 2908 && Fixup2.r_symbolnum < cSyms, 2909 KLDR_ERR_BAD_FIXUP); 2910 2911 pSym = &paSyms[Fixup.r.r_symbolnum]; 2912 KLDRMODMACHO_CHECK_RETURN(!(pSym->n_type & MACHO_N_STAB), KLDR_ERR_BAD_FIXUP); 2913 2914 /* Add it's value to SymAddr. */ 2915 switch (pSym->n_type & MACHO_N_TYPE) 2916 { 2917 case MACHO_N_SECT: 2918 { 2919 PKLDRMODMACHOSECT pSymSect; 2920 KLDRMODMACHO_CHECK_RETURN((KU32)pSym->n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL); 2921 pSymSect = &pModMachO->paSections[pSym->n_sect - 1]; 2922 SymAddr += pSym->n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 2923 break; 2924 } 2925 2926 case MACHO_N_UNDF: 2927 case MACHO_N_ABS: 2928 SymAddr += pSym->n_value; 2929 break; 2930 2931 case MACHO_N_INDR: 2932 case MACHO_N_PBUD: 2933 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); 2934 default: 2935 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL); 2936 } 2937 } 2938 break; 2939 } 2940 } 2941 else 2942 { 2943 /* verify against fixup type */ 2944 switch (Fixup.r.r_type) 2945 { 2946 case X86_64_RELOC_UNSIGNED: 2947 case X86_64_RELOC_SIGNED: 2948 case X86_64_RELOC_BRANCH: 2949 /*case X86_64_RELOC_GOT_LOAD:*/ 2950 /*case X86_64_RELOC_GOT: */ 2951 /*case X86_64_RELOC_SUBTRACTOR: - ???*/ 2952 case X86_64_RELOC_SIGNED_1: 2953 case X86_64_RELOC_SIGNED_2: 2954 case X86_64_RELOC_SIGNED_4: 2955 break; 2956 default: 2957 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP); 2958 } 2959 if (Fixup.r.r_symbolnum != R_ABS) 2960 { 2961 PKLDRMODMACHOSECT pSymSect; 2962 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_symbolnum <= pModMachO->cSections, KLDR_ERR_BAD_FIXUP); 2963 pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1]; 2964 2965 SymAddr -= pSymSect->LinkAddress; 2966 SymAddr += pSymSect->RVA + NewBaseAddress; 2967 } 2968 } 2969 2970 /* adjust for PC relative */ 2971 if (Fixup.r.r_pcrel) 2972 SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress; 2973 2974 /* 2975 * Write back the fixed up value. 2976 */ 2977 switch (Fixup.r.r_length) 2978 { 2979 case 3: 2980 *uFix.pu64 = (KU64)SymAddr; 2981 break; 2982 case 2: 2983 KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel || Fixup.r.r_type == X86_64_RELOC_SUBTRACTOR, KLDR_ERR_BAD_FIXUP); 2984 KLDRMODMACHO_CHECK_RETURN((KI32)SymAddr == (KI64)SymAddr, KLDR_ERR_ADDRESS_OVERFLOW); 2985 *uFix.pu32 = (KU32)SymAddr; 2986 break; 2987 default: 2988 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP); 2989 } 2990 } 2991 2992 return 0; 2993 } 2994 2995 2996 /** 2115 2997 * Loads the symbol table for a MH_OBJECT file. 2116 2998 * … … 2133 3015 2134 3016 /* sanity */ 2135 if ( !pModMachO->offSymbols2136 || (pModMachO->cchStrings && !pModMachO->offStrings))2137 return KLDR_ERR_MACHO_BAD_OBJECT_FILE;3017 KLDRMODMACHO_CHECK_RETURN( pModMachO->offSymbols 3018 && (!pModMachO->cchStrings || pModMachO->offStrings), 3019 KLDR_ERR_MACHO_BAD_OBJECT_FILE); 2138 3020 2139 3021 /* allocate */ … … 2143 3025 : sizeof(macho_nlist_64_t); 2144 3026 cbSyms = pModMachO->cSymbols * cbSym; 2145 if (cbSyms / cbSym != pModMachO->cSymbols) 2146 return KLDR_ERR_SIZE_OVERFLOW; 3027 KLDRMODMACHO_CHECK_RETURN(cbSyms / cbSym == pModMachO->cSymbols, KLDR_ERR_SIZE_OVERFLOW); 2147 3028 rc = KERR_NO_MEMORY; 2148 3029 pvSyms = kHlpAlloc(cbSyms); … … 2222 3103 /* allocate the memory. */ 2223 3104 cbFixups = cFixups * sizeof(*paFixups); 2224 if (cbFixups / sizeof(*paFixups) != cFixups) 2225 return KLDR_ERR_SIZE_OVERFLOW; 3105 KLDRMODMACHO_CHECK_RETURN(cbFixups / sizeof(*paFixups) == cFixups, KLDR_ERR_SIZE_OVERFLOW); 2226 3106 paFixups = (macho_relocation_info_t *)kHlpAlloc(cbFixups); 2227 3107 if (!paFixups) … … 2317 3197 */ 2318 3198 if (pModMachO->fMapUsingLoadCommandSections) 2319 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */3199 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 2320 3200 else 2321 3201 { … … 2329 3209 continue; 2330 3210 rc = kRdrRead(pMod->pRdr, 2331 2332 2333 3211 (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->LinkAddress), 3212 pMod->aSegments[i].cbFile, 3213 pMod->aSegments[i].offFile); 2334 3214 if (rc) 2335 3215 return rc; … … 2340 3220 * Perform relocations. 2341 3221 */ 2342 return kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser); 3222 rc = kldrModMachORelocateBits(pMod, pvBits, BaseAddress, pModMachO->LinkAddress, pfnGetImport, pvUser); 3223 if (rc) 3224 return rc; 3225 3226 /* 3227 * Construct the global offset table if necessary, it's always the last 3228 * segment when present. 3229 */ 3230 if (pModMachO->fMakeGot) 3231 rc = kldrModMachOMakeGOT(pModMachO, pvBits, BaseAddress); 3232 return rc; 3233 } 3234 3235 3236 /** 3237 * Builds the GOT. 3238 * 3239 * Assumes the symbol table has all external symbols resolved correctly and that 3240 * the bits has been cleared up front. 3241 */ 3242 static int kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR NewBaseAddress) 3243 { 3244 KU32 iSym = pModMachO->cSymbols; 3245 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 3246 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 3247 { 3248 macho_nlist_32_t const *paSyms = (macho_nlist_32_t const *)pModMachO->pvaSymbols; 3249 KU32 *paGOT = (KU32 *)((KU8 *)pvBits + pModMachO->GotRVA); 3250 while (iSym-- > 0) 3251 switch (paSyms[iSym].n_type & MACHO_N_TYPE) 3252 { 3253 case MACHO_N_SECT: 3254 { 3255 PKLDRMODMACHOSECT pSymSect; 3256 KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL); 3257 pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1]; 3258 paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 3259 break; 3260 } 3261 3262 case MACHO_N_UNDF: 3263 case MACHO_N_ABS: 3264 paGOT[iSym] = paSyms[iSym].n_value; 3265 break; 3266 } 3267 } 3268 else 3269 { 3270 macho_nlist_64_t const *paSyms = (macho_nlist_64_t const *)pModMachO->pvaSymbols; 3271 KU64 *paGOT = (KU64 *)((KU8 *)pvBits + pModMachO->GotRVA); 3272 while (iSym-- > 0) 3273 switch (paSyms[iSym].n_type & MACHO_N_TYPE) 3274 { 3275 case MACHO_N_SECT: 3276 { 3277 PKLDRMODMACHOSECT pSymSect; 3278 KLDRMODMACHO_CHECK_RETURN((KU32)paSyms[iSym].n_sect - 1 <= pModMachO->cSections, KLDR_ERR_MACHO_BAD_SYMBOL); 3279 pSymSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1]; 3280 paGOT[iSym] = paSyms[iSym].n_value - pSymSect->LinkAddress + pSymSect->RVA + NewBaseAddress; 3281 break; 3282 } 3283 3284 case MACHO_N_UNDF: 3285 case MACHO_N_ABS: 3286 paGOT[iSym] = paSyms[iSym].n_value; 3287 break; 3288 } 3289 } 3290 return 0; 2343 3291 } 2344 3292
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器