diff --git a/src/macho/Constants.go b/src/macho/Constants.go index 1715fe6..f74711a 100644 --- a/src/macho/Constants.go +++ b/src/macho/Constants.go @@ -34,8 +34,9 @@ func SizeCommands(libs dll.List) int { size := sizeCommands for lib := range libs.All() { + libName := resolveLibName(lib.Name) size += DylibCommandSize - size += exe.Align(len(lib.Name)+1, 8) + size += exe.Align(len(libName), 8) } return size diff --git a/src/macho/LinkEdit.go b/src/macho/LinkEdit.go index f6f1c0f..ad324a5 100644 --- a/src/macho/LinkEdit.go +++ b/src/macho/LinkEdit.go @@ -50,7 +50,7 @@ func createLinkEditSegment(libs dll.List, data *exe.Section, pageSize int) []byt numFunctions := libs.CountFunctions() linkEditSize := ChainedFixupsHeaderSize + ChainedStartsInImageSize + ChainedStartsInSegmentSize importsOffset := exe.Align(linkEditSize, 16) - importsSize := numFunctions * 8 + importsSize := numFunctions * 4 symbolsOffset := exe.Align(importsOffset+importsSize, 16) linkEdit := LinkEdit{ @@ -87,16 +87,32 @@ func createLinkEditSegment(libs dll.List, data *exe.Section, pageSize int) []byt exe.PadBuffer(&buffer, 16) symbols := strings.Builder{} libOrdinal := 1 + ordinal := 0 for lib := range libs.All() { for _, name := range lib.Functions { + // Imports table nameOffset := symbols.Len() + symbols.WriteByte('_') symbols.WriteString(name) symbols.WriteByte(0) weakImport := 0 dyldChainedImport := (nameOffset << 9) + (weakImport << 8) + libOrdinal - binary.Write(&buffer, binary.LittleEndian, dyldChainedImport) - data.Bytes = binary.LittleEndian.AppendUint64(data.Bytes, 0) + binary.Write(&buffer, binary.LittleEndian, uint64(dyldChainedImport)) + + // Actual address location + addend := 0 + reserved := 0 + next := 2 + + if ordinal == numFunctions-1 { + next = 0 + } + + bind := 1 + dyldChainedPtr64Bind := bind<<63 + next<<51 + reserved<<32 + addend<<24 + ordinal + data.Bytes = binary.LittleEndian.AppendUint64(data.Bytes, uint64(dyldChainedPtr64Bind)) + ordinal++ } libOrdinal++ diff --git a/src/macho/MachO.go b/src/macho/MachO.go index 9fe3598..720445e 100644 --- a/src/macho/MachO.go +++ b/src/macho/MachO.go @@ -153,7 +153,8 @@ func Write(writer io.WriteSeeker, build *config.Build, codeBytes []byte, dataByt } for lib := range libs.All() { - paddedName := exe.PadSlice([]byte(lib.Name+"\000"), 8) + libName := resolveLibName(lib.Name) + paddedName := exe.PadSlice([]byte(libName), 8) m.Libs = append(m.Libs, Dylib{ DylibCommand: DylibCommand{ diff --git a/src/macho/resolveLibName.go b/src/macho/resolveLibName.go new file mode 100644 index 0000000..c24189c --- /dev/null +++ b/src/macho/resolveLibName.go @@ -0,0 +1,10 @@ +package macho + +// resolveLibName returns the real libc library name and also appends the '.dylib' suffix as well as a 0-byte. +func resolveLibName(libName string) string { + if libName == "libc" { + libName = "libSystem.B" + } + + return libName + ".dylib\000" +} \ No newline at end of file