@@ -99,7 +99,7 @@ def _enumerateExports(self) -> None:
9999 # get an initial list of dependencies
100100 if dylibs := self ._machoCtx .getLoadCommand (DEP_LCS , multiple = True ):
101101 for dylib in dylibs :
102- if depInfo := self ._getDepInfo (dylib ):
102+ if depInfo := self ._getDepInfo (dylib , self . _machoCtx ):
103103 depsQueue .append (depInfo )
104104 pass
105105
@@ -123,8 +123,8 @@ def _enumerateExports(self) -> None:
123123 if dylibs := depInfo .context .getLoadCommand (DEP_LCS , multiple = True ):
124124 for dylib in dylibs :
125125 if dylib .cmd == LoadCommands .LC_REEXPORT_DYLIB :
126- if depInfo := self ._getDepInfo (dylib ):
127- depsQueue .append (depInfo )
126+ if info := self ._getDepInfo (dylib , depInfo . context ):
127+ depsQueue .append (info )
128128 pass
129129
130130 # check for any ReExport exports
@@ -137,8 +137,8 @@ def _enumerateExports(self) -> None:
137137
138138 for ordinal in reExportOrdinals :
139139 dylib = dylibs [ordinal - 1 ]
140- if depInfo := self ._getDepInfo (dylib ):
141- depsQueue .append (depInfo )
140+ if info := self ._getDepInfo (dylib , depInfo . context ):
141+ depsQueue .append (info )
142142 pass
143143 pass
144144
@@ -161,12 +161,12 @@ def _enumerateExports(self) -> None:
161161 self ._logger .warning (f"No root export for ReExport with symbol { name } " )
162162 pass
163163
164- def _getDepInfo (self , dylib : dylib_command ) -> _DependencyInfo :
164+ def _getDepInfo (self , dylib : dylib_command , context : MachOContext ) -> _DependencyInfo :
165165 """Given a dylib command, get dependency info.
166166 """
167167
168168 dylibPathOff = dylib ._fileOff_ + dylib .dylib .name .offset
169- dylibPath = self . _machoCtx .fileCtx .readString (dylibPathOff )
169+ dylibPath = context .fileCtx .readString (dylibPathOff )
170170 if dylibPath not in self ._images :
171171 self ._logger .warning (f"Unable to find dependency: { dylibPath } " )
172172 return None
@@ -526,7 +526,7 @@ def getResolverData(self, address: int) -> Tuple[int, int]:
526526 return None
527527
528528 # test stp and mov
529- stp , mov = ctx .fileCtx .readFormat (stubOff , "<II" )
529+ stp , mov = ctx .fileCtx .readFormat ("<II" , stubOff )
530530 if (
531531 (stp & 0x7FC00000 ) != 0x29800000
532532 or (mov & 0x7F3FFC00 ) != 0x11000000
@@ -563,16 +563,16 @@ def getResolverData(self, address: int) -> Tuple[int, int]:
563563 return None
564564
565565 # Test if there is a stp before the bl and a ldp before the braaz
566- adrp = ctx .fileCtx .readFormat (blInstrOff + 4 , "<I" )[0 ]
567- ldp = ctx .fileCtx .readFormat (branchInstrOff - 4 , "<I" )[0 ]
566+ adrp = ctx .fileCtx .readFormat ("<I" , blInstrOff + 4 )[0 ]
567+ ldp = ctx .fileCtx .readFormat ("<I" , branchInstrOff - 4 )[0 ]
568568 if (
569569 (adrp & 0x9F00001F ) != 0x90000010
570570 or (ldp & 0x7FC00000 ) != 0x28C00000
571571 ):
572572 return None
573573
574574 # Hopefully it's a resolver...
575- imm = (ctx .fileCtx .readFormat (blInstrOff , "<I" )[0 ] & 0x3FFFFFF ) << 2
575+ imm = (ctx .fileCtx .readFormat ("<I" , blInstrOff )[0 ] & 0x3FFFFFF ) << 2
576576 imm = self .signExtend (imm , 28 )
577577 blResult = address + (blInstrOff - stubOff ) + imm
578578
@@ -619,7 +619,7 @@ def _getStubNormalLdrAddr(self, address: int) -> int:
619619 if stubOff is None :
620620 return None
621621
622- adrp , ldr , br = ctx .fileCtx .readFormat (stubOff , "<III" )
622+ adrp , ldr , br = ctx .fileCtx .readFormat ("<III" , stubOff )
623623
624624 # verify
625625 if (
@@ -657,8 +657,8 @@ def _getAuthStubNormalLdrAddr(self, address: int) -> int:
657657 return None
658658
659659 adrp , add , ldr , braa = ctx .fileCtx .readFormat (
660- stubOff ,
661- "<IIII"
660+ "<IIII" ,
661+ stubOff
662662 )
663663
664664 # verify
@@ -696,7 +696,7 @@ def _getStubNormalTarget(self, address: int) -> int:
696696 if stubOff is None :
697697 return None
698698
699- adrp , ldr , br = ctx .fileCtx .readFormat (stubOff , "<III" )
699+ adrp , ldr , br = ctx .fileCtx .readFormat ("<III" , stubOff )
700700
701701 # verify
702702 if (
@@ -729,7 +729,7 @@ def _getStubOptimizedTarget(self, address: int) -> int:
729729 if stubOff is None :
730730 return None
731731
732- adrp , add , br = ctx .fileCtx .readFormat (stubOff , "<III" )
732+ adrp , add , br = ctx .fileCtx .readFormat ("<III" , stubOff )
733733
734734 # verify
735735 if (
@@ -762,7 +762,7 @@ def _getAuthStubNormalTarget(self, address: int) -> int:
762762 if stubOff is None :
763763 return None
764764
765- adrp , add , ldr , braa = ctx .fileCtx .readFormat (stubOff , "<IIII" )
765+ adrp , add , ldr , braa = ctx .fileCtx .readFormat ("<IIII" , stubOff )
766766
767767 # verify
768768 if (
@@ -802,7 +802,7 @@ def _getAuthStubOptimizedTarget(self, address: int) -> int:
802802 if stubOff is None :
803803 return None
804804
805- adrp , add , br , trap = ctx .fileCtx .readFormat (stubOff , "<IIII" )
805+ adrp , add , br , trap = ctx .fileCtx .readFormat ("<IIII" , stubOff )
806806
807807 # verify
808808 if (
@@ -835,7 +835,7 @@ def _getAuthStubResolverTarget(self, address: int) -> int:
835835 if stubOff is None :
836836 return None
837837
838- adrp , ldr , braaz = ctx .fileCtx .readFormat (stubOff , "<III" )
838+ adrp , ldr , braaz = ctx .fileCtx .readFormat ("<III" , stubOff )
839839
840840 # verify
841841 if (
@@ -1117,8 +1117,8 @@ def _addToMap(ptrSymbol: bytes, ptrAddr: int, section: section_64):
11171117
11181118 # Try to symbolize though indirect symbol entries
11191119 symbolIndex = linkeditFile .readFormat (
1120- self . _dysymtab . indirectsymoff + (( sect . reserved1 + i ) * 4 ) ,
1121- "<I"
1120+ "<I" ,
1121+ self . _dysymtab . indirectsymoff + (( sect . reserved1 + i ) * 4 )
11221122 )[0 ]
11231123 if (
11241124 symbolIndex != 0
@@ -1127,7 +1127,7 @@ def _addToMap(ptrSymbol: bytes, ptrAddr: int, section: section_64):
11271127 and symbolIndex != (INDIRECT_SYMBOL_ABS | INDIRECT_SYMBOL_LOCAL )
11281128 ):
11291129 symbolEntry = nlist_64 (
1130- linkeditFile ,
1130+ linkeditFile . file ,
11311131 self ._symtab .symoff + (symbolIndex * nlist_64 .SIZE )
11321132 )
11331133 symbol = linkeditFile .readString (
@@ -1254,6 +1254,12 @@ def _addToMap(stubName: bytes, stubAddr: int):
12541254 self ._machoCtx .segments [b"__LINKEDIT" ].seg .vmaddr
12551255 )
12561256
1257+ textFile = self ._machoCtx .fileForAddr (
1258+ self ._machoCtx .segments [b"__TEXT" ].seg .vmaddr
1259+ )
1260+
1261+ symbolPtrFile = None
1262+
12571263 for segment in self ._machoCtx .segmentsI :
12581264 for sect in segment .sectsI :
12591265 if sect .flags & SECTION_TYPE == S_SYMBOL_STUBS :
@@ -1267,8 +1273,8 @@ def _addToMap(stubName: bytes, stubAddr: int):
12671273
12681274 # Try to symbolize though indirect symbol entries
12691275 symbolIndex = linkeditFile .readFormat (
1270- self . _dysymtab . indirectsymoff + (( sect . reserved1 + i ) * 4 ) ,
1271- "<I"
1276+ "<I" ,
1277+ self . _dysymtab . indirectsymoff + (( sect . reserved1 + i ) * 4 )
12721278 )[0 ]
12731279
12741280 if (
@@ -1339,24 +1345,32 @@ def _addToMap(stubName: bytes, stubAddr: int):
13391345 elif stubFormat == _StubFormat .StubOptimized :
13401346 # only need to relink stub
13411347 newStub = self ._arm64Utils .generateStubNormal (stubAddr , symPtrAddr )
1342- stubOff , ctx = self ._dyldCtx .convertAddr (stubAddr )
1343- ctx . fileCtx .writeBytes (stubOff , newStub )
1348+ stubOff = self ._dyldCtx .convertAddr (stubAddr )[ 0 ]
1349+ textFile .writeBytes (stubOff , newStub )
13441350 continue
13451351
13461352 elif stubFormat == _StubFormat .AuthStubNormal :
13471353 # only need to relink symbol pointer
1348- symPtrOff , ctx = self ._dyldCtx .convertAddr (symPtrAddr )
1349- ctx .fileCtx .writeBytes (symPtrOff , struct .pack ("<Q" , stubAddr ))
1354+ symPtrOff = self ._dyldCtx .convertAddr (symPtrAddr )[0 ]
1355+
1356+ if symbolPtrFile :
1357+ symbolPtrFile = self ._machoCtx .fileForAddr (symPtrAddr )
1358+ pass
1359+
1360+ symbolPtrFile .writeBytes (symPtrOff , struct .pack ("<Q" , stubAddr ))
13501361 continue
13511362
13521363 elif stubFormat == _StubFormat .AuthStubOptimized :
13531364 # need to relink both the stub and the symbol pointer
1354- symPtrOff , ctx = self ._dyldCtx .convertAddr (symPtrAddr )
1355- ctx .fileCtx .writeBytes (symPtrOff , struct .pack ("<Q" , stubAddr ))
1365+ symPtrOff = self ._dyldCtx .convertAddr (symPtrAddr )[0 ]
1366+ if symbolPtrFile :
1367+ symbolPtrFile = self ._machoCtx .fileForAddr (symPtrAddr )
1368+ pass
1369+ symbolPtrFile .writeBytes (symPtrOff , struct .pack ("<Q" , stubAddr ))
13561370
13571371 newStub = self ._arm64Utils .generateAuthStubNormal (stubAddr , symPtrAddr )
13581372 stubOff , ctx = self ._dyldCtx .convertAddr (stubAddr )
1359- ctx . fileCtx .writeBytes (stubOff , newStub )
1373+ textFile .writeBytes (stubOff , newStub )
13601374 continue
13611375
13621376 elif stubFormat == _StubFormat .AuthStubResolver :
@@ -1395,14 +1409,15 @@ def _fixCallsites(self, stubMap: Dict[bytes, Tuple[int]]) -> None:
13951409 # Section offsets by section_64.offset are sometimes
13961410 # inaccurate, like in libcrypto.dylib
13971411 textOff = self ._dyldCtx .convertAddr (textAddr )[0 ]
1412+ textFile = self ._machoCtx .fileForAddr (textAddr )
13981413
13991414 for sectOff in range (0 , textSect .size , 4 ):
14001415 # We are only looking for bl and b instructions only.
14011416 # Theses instructions are only identical by their top
14021417 # most byte. By only looking at the top byte, we can
14031418 # save a lot of time.
14041419 instrOff = textOff + sectOff
1405- instrTop = self . _machoCtx .file [instrOff + 3 ] & 0xFC
1420+ instrTop = textFile .file [instrOff + 3 ] & 0xFC
14061421
14071422 if (
14081423 instrTop != 0x94 # bl
@@ -1411,7 +1426,7 @@ def _fixCallsites(self, stubMap: Dict[bytes, Tuple[int]]) -> None:
14111426 continue
14121427
14131428 # get the target of the branch
1414- brInstr = self . _machoCtx . readFormat (instrOff , "<I" )[0 ]
1429+ brInstr = textFile . readFormat ("<I" , instrOff )[0 ]
14151430 imm26 = brInstr & 0x3FFFFFF
14161431 brOff = self ._arm64Utils .signExtend (imm26 << 2 , 28 )
14171432
@@ -1428,7 +1443,7 @@ def _fixCallsites(self, stubMap: Dict[bytes, Tuple[int]]) -> None:
14281443 # Sometimes there are bytes of data in the text section
14291444 # that match the bl and b filter, these seem to follow a
14301445 # BR or other branch, skip these.
1431- lastInstTop = self . _machoCtx .file [instrOff + 3 ] & 0xFC
1446+ lastInstTop = textFile .file [instrOff + 3 ] & 0xFC
14321447 if (
14331448 lastInstTop == 0x94 # bl
14341449 or lastInstTop == 0x14 # b
@@ -1442,7 +1457,7 @@ def _fixCallsites(self, stubMap: Dict[bytes, Tuple[int]]) -> None:
14421457 stubSymbol = next ((sym for sym in funcSymbols if sym in stubMap ), None )
14431458 if not stubSymbol :
14441459 # Same as above
1445- lastInstTop = self . _machoCtx .file [instrOff + 3 ] & 0xFC
1460+ lastInstTop = textFile .file [instrOff + 3 ] & 0xFC
14461461 if (
14471462 lastInstTop == 0x94 # bl
14481463 or lastInstTop == 0x14 # b
@@ -1457,7 +1472,7 @@ def _fixCallsites(self, stubMap: Dict[bytes, Tuple[int]]) -> None:
14571472 stubAddr = stubMap [stubSymbol ][0 ]
14581473 imm26 = (stubAddr - brAddr ) >> 2
14591474 brInstr = (brInstr & 0xFC000000 ) | imm26
1460- struct .pack_into ("<I" , self . _machoCtx .file , instrOff , brInstr )
1475+ struct .pack_into ("<I" , textFile .file , instrOff , brInstr )
14611476
14621477 self ._statusBar .update (status = "Fixing Callsites" )
14631478 pass
@@ -1481,6 +1496,10 @@ def _fixIndirectSymbols(
14811496
14821497 self ._statusBar .update (status = "Fixing Indirect Symbols" )
14831498
1499+ linkeditFile = self ._machoCtx .fileForAddr (
1500+ self ._machoCtx .segments [b"__LINKEDIT" ].seg .vmaddr
1501+ )
1502+
14841503 currentSymbolIndex = self ._dysymtab .iundefsym + self ._dysymtab .nundefsym
14851504 currentStringIndex = self ._symtab .strsize
14861505
@@ -1498,7 +1517,7 @@ def _fixIndirectSymbols(
14981517 self ._statusBar .update ()
14991518
15001519 entryOffset = self ._dysymtab .indirectsymoff + (i * 4 )
1501- entry = self . _machoCtx . readFormat (entryOffset , "<I" )[0 ]
1520+ entry = linkeditFile . readFormat ("<I" , entryOffset )[0 ]
15021521
15031522 if entry != 0 :
15041523 continue
@@ -1521,7 +1540,7 @@ def _fixIndirectSymbols(
15211540 currentStringIndex += len (stubSymbol )
15221541
15231542 # update the indirect entry and add it
1524- self . _machoCtx .writeBytes (
1543+ linkeditFile .writeBytes (
15251544 entryOffset ,
15261545 struct .pack ("<I" , currentSymbolIndex )
15271546 )
@@ -1542,7 +1561,7 @@ def _fixIndirectSymbols(
15421561 self ._statusBar .update ()
15431562
15441563 entryOffset = self ._dysymtab .indirectsymoff + (i * 4 )
1545- entry = self . _machoCtx . readFormat (entryOffset , "<I" )[0 ]
1564+ entry = linkeditFile . readFormat ("<I" , entryOffset )[0 ]
15461565
15471566 if entry != 0 :
15481567 continue
@@ -1565,7 +1584,7 @@ def _fixIndirectSymbols(
15651584 currentStringIndex += len (ptrSymbol )
15661585
15671586 # update the indirect entry and add it
1568- self . _machoCtx .writeBytes (
1587+ linkeditFile .writeBytes (
15691588 entryOffset ,
15701589 struct .pack ("<I" , currentSymbolIndex )
15711590 )
@@ -1586,7 +1605,7 @@ def _fixIndirectSymbols(
15861605 self ._statusBar .update ()
15871606
15881607 entryOffset = self ._dysymtab .indirectsymoff + (i * 4 )
1589- entry = self . _machoCtx . readFormat (entryOffset , "<I" )[0 ]
1608+ entry = linkeditFile . readFormat ("<I" , entryOffset )[0 ]
15901609
15911610 if entry != 0 :
15921611 continue
@@ -1602,7 +1621,7 @@ def _fixIndirectSymbols(
16021621 self ._statusBar .update ()
16031622
16041623 entryOffset = self ._dysymtab .indirectsymoff + (i * 4 )
1605- entry = self . _machoCtx . readFormat (entryOffset , "<I" )[0 ]
1624+ entry = linkeditFile . readFormat ("<I" , entryOffset )[0 ]
16061625
16071626 if entry != 0 :
16081627 continue
@@ -1626,11 +1645,11 @@ def _fixIndirectSymbols(
16261645 self ._statusBar .update ()
16271646
16281647 # add the new data and update the load commands
1629- self . _machoCtx .writeBytes (
1648+ linkeditFile .writeBytes (
16301649 self ._symtab .symoff + (self ._symtab .nsyms * nlist_64 .SIZE ),
16311650 newSymbols
16321651 )
1633- self . _machoCtx .writeBytes (
1652+ linkeditFile .writeBytes (
16341653 self ._symtab .stroff + self ._symtab .strsize ,
16351654 newStrings
16361655 )
0 commit comments