compress the extracted information
This commit is contained in:
parent
2eede8f9b2
commit
ed2f09348e
@ -1,7 +1,8 @@
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
// "fmt"
|
||||||
|
"sort"
|
||||||
// log "github.com/sirupsen/logrus"
|
// log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
. "ios-wrapper/internal/wrapper/ofile"
|
. "ios-wrapper/internal/wrapper/ofile"
|
||||||
@ -11,25 +12,46 @@ import (
|
|||||||
type saveImports struct{}
|
type saveImports struct{}
|
||||||
|
|
||||||
func (action *saveImports) withMacho(mf *MachoFile) error {
|
func (action *saveImports) withMacho(mf *MachoFile) error {
|
||||||
calculateHash := func(name string) uint32 {
|
// calculateHash := func(name string) uint32 {
|
||||||
var h uint32 = 0x811c9dc5
|
// var h uint32 = 0x811c9dc5
|
||||||
for _, s := range name {
|
// for _, s := range name {
|
||||||
h ^= uint32(s)
|
// h ^= uint32(s)
|
||||||
h *= 0x01000193
|
// h *= 0x01000193
|
||||||
}
|
// }
|
||||||
return h
|
// return h
|
||||||
}
|
// }
|
||||||
|
|
||||||
mc := mf.Context()
|
mc := mf.Context()
|
||||||
symbols := []*protomodel.MachoInfo_BindSymbol{}
|
// symbols_storage := []*protomodel.MachoInfo_AllImportedSymbols{}
|
||||||
fmt.Println("struct imported_symbol {const char* name; const char* lib; uint32_t hash; int segment_i; uint64_t offset;};")
|
symbols_raw := mc.CollectBindSymbols()
|
||||||
fmt.Println("const char* lib_to_resolve = \"main\";")
|
sort.Slice(symbols_raw, func(i, j int) bool {
|
||||||
fmt.Println("struct imported_symbol imported_table[] = {")
|
orderedByLibrary := symbols_raw[i].Dylib() < symbols_raw[j].Dylib()
|
||||||
for _, symbol := range mc.CollectBindSymbols() {
|
if symbols_raw[i].Dylib() == symbols_raw[j].Dylib() {
|
||||||
|
orderedBySymbol := symbols_raw[i].Name() < symbols_raw[j].Name()
|
||||||
|
return orderedBySymbol
|
||||||
|
}
|
||||||
|
return orderedByLibrary
|
||||||
|
})
|
||||||
|
|
||||||
|
libs := []string{}
|
||||||
|
symbols := []string{}
|
||||||
|
tables := []*protomodel.MachoInfo_LibraryImportedSymbols{}
|
||||||
|
|
||||||
|
var current_table *protomodel.MachoInfo_LibraryImportedSymbols
|
||||||
|
|
||||||
|
current_lib := ""
|
||||||
|
current_symbol := ""
|
||||||
|
|
||||||
|
current_lib_idx := -1
|
||||||
|
current_symbol_idx := -1
|
||||||
|
|
||||||
|
// now we expect everything is sorted and easier to build strings tables
|
||||||
|
// this is not fully optimized, there can be repeated symbol name in different libraries
|
||||||
|
for _, symbol := range symbols_raw {
|
||||||
if symbol.Type() != "lazy" {
|
if symbol.Type() != "lazy" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dylib_hash := calculateHash(symbol.Dylib())
|
// dylib_hash := calculateHash(symbol.Dylib())
|
||||||
seg := mc.Segments()[symbol.Segment()]
|
seg := mc.Segments()[symbol.Segment()]
|
||||||
|
|
||||||
var offset uint64
|
var offset uint64
|
||||||
@ -42,22 +64,48 @@ func (action *saveImports) withMacho(mf *MachoFile) error {
|
|||||||
offset = symbol.Address() - seg.Fileoff()
|
offset = symbol.Address() - seg.Fileoff()
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
if current_lib != symbol.Dylib() {
|
||||||
symbol.Name(), symbol.Dylib(), dylib_hash, symbol.Segment(), offset)
|
current_lib_idx += len(current_lib) + 1
|
||||||
|
current_lib = symbol.Dylib()
|
||||||
symbols = append(symbols,
|
libs = append(libs, symbol.Dylib())
|
||||||
&protomodel.MachoInfo_BindSymbol{
|
tables = append(tables, &protomodel.MachoInfo_LibraryImportedSymbols{
|
||||||
Name: symbol.Name(),
|
LibIndex: uint32(current_lib_idx),
|
||||||
Libname: symbol.Dylib(),
|
Nsymbols: 0,
|
||||||
Libhash: dylib_hash,
|
Symbols: []*protomodel.MachoInfo_SymbolTable{},
|
||||||
Segment: symbol.Segment(),
|
|
||||||
Offset: offset,
|
|
||||||
})
|
})
|
||||||
|
current_table = tables[len(tables)-1]
|
||||||
|
}
|
||||||
|
if current_symbol != symbol.Name() {
|
||||||
|
current_symbol_idx += len(current_symbol) + 1
|
||||||
|
current_symbol = symbol.Name()
|
||||||
|
symbols = append(symbols, symbol.Name())
|
||||||
|
}
|
||||||
|
current_table.Nsymbols += 1
|
||||||
|
current_table.Symbols = append(current_table.Symbols, &protomodel.MachoInfo_SymbolTable{
|
||||||
|
SymbolIndex: uint32(current_symbol_idx),
|
||||||
|
SegmentIndex: symbol.Segment(),
|
||||||
|
Offset: uint32(offset),
|
||||||
|
})
|
||||||
|
|
||||||
|
// fmt.Printf("{\"%s\", \"%s\", 0x%x, 0x%x, 0x%x},\n",
|
||||||
|
// symbol.Name(), symbol.Dylib(), symbol.Segment(), offset)
|
||||||
|
|
||||||
|
// symbols = append(symbols,
|
||||||
|
// &protomodel.MachoInfo_BindSymbol{
|
||||||
|
// Name: symbol.Name(),
|
||||||
|
// Libname: symbol.Dylib(),
|
||||||
|
// Libhash: dylib_hash,
|
||||||
|
// Segment: symbol.Segment(),
|
||||||
|
// Offset: offset,
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
fmt.Println("};")
|
mf.Info().Symbols = &protomodel.MachoInfo_AllImportedSymbols{
|
||||||
fmt.Printf("uint32_t nimports = %d;\n", len(symbols))
|
Libs: libs,
|
||||||
mf.Info().Symbols = symbols
|
Symbols: symbols,
|
||||||
|
Tables: tables,
|
||||||
|
}
|
||||||
|
|
||||||
|
mf.Info().Main = mc.Main()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package wrapper
|
package wrapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
// "strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -194,11 +195,11 @@ func displayBcell(bfile string) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
fmt.Printf(" | Bind Symbols:\n")
|
fmt.Printf(" | Bind Symbols:\n")
|
||||||
for _, symbol := range info.Symbols {
|
// for _, symbol := range info.Symbols {
|
||||||
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
|
// lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
|
||||||
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
|
// fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
|
||||||
fmt.Printf(" | from=%s\n", lib)
|
// fmt.Printf(" | from=%s\n", lib)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,33 +232,73 @@ func resolveAddresses(dwarf string, load string, addresses []string) {
|
|||||||
|
|
||||||
func bcell2header(bfile string, header string) {
|
func bcell2header(bfile string, header string) {
|
||||||
raw_data, err := ioutil.ReadFile(bfile)
|
raw_data, err := ioutil.ReadFile(bfile)
|
||||||
if err != nil {
|
|
||||||
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (1)")
|
|
||||||
}
|
|
||||||
data := &protomodel.BcellFile{}
|
data := &protomodel.BcellFile{}
|
||||||
err = proto.Unmarshal(raw_data, data)
|
err = proto.Unmarshal(raw_data, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic("Invalid Protobuf<BcellFile> bcell.dat (2)")
|
log.Panic("Invalid Protobuf<BcellFile> bcell.dat")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("[+] User Config: %+v\n", data.BcellConfig)
|
f, err := os.Create(header)
|
||||||
for arch, info := range data.MachoInfos {
|
if err != nil {
|
||||||
fmt.Printf("[+] Arch %s:\n", arch)
|
log.Panic("Cannot open header file for writing")
|
||||||
fmt.Printf(" | PointerSize : %+v\n", info.PointerSize)
|
|
||||||
fmt.Printf(" | Image Base : 0x%x\n", info.ImageBase)
|
|
||||||
fmt.Printf(" | Init Pointers:\n")
|
|
||||||
for _, init_ptr := range info.InitPointers {
|
|
||||||
fmt.Printf(
|
|
||||||
" | offset 0x%x => addr 0x%x\n",
|
|
||||||
init_ptr.Offset,
|
|
||||||
init_ptr.Value,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fmt.Printf(" | Bind Symbols:\n")
|
|
||||||
for _, symbol := range info.Symbols {
|
|
||||||
lib := strings.Replace(symbol.Libname, "/System/Library/Frameworks/", "", 1)
|
|
||||||
fmt.Printf(" | %s offset=0x%x segmentID=0x%x\n", symbol.Name, symbol.Offset, symbol.Segment)
|
|
||||||
fmt.Printf(" | from=%s\n", lib)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
w := bufio.NewWriter(f)
|
||||||
|
|
||||||
|
// fmt.Printf("[+] User Config: %+v\n", data.BcellConfig)
|
||||||
|
fmt.Fprintf(w, "#include<stdint.h>\n")
|
||||||
|
fmt.Fprintf(w, "namespace bshield_data{\n")
|
||||||
|
for arch, info := range data.MachoInfos {
|
||||||
|
fmt.Fprintf(w, "const char* arch = \"%s\";\n", arch)
|
||||||
|
fmt.Fprintf(w, "unsigned int pointer_size = %d;\n", info.PointerSize)
|
||||||
|
fmt.Fprintf(w, "uint64_t image_base = 0x%x;\n", info.ImageBase)
|
||||||
|
fmt.Fprintf(w, "uint64_t main = 0x%x;\n", info.Main)
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "struct init_pointer {uint64_t offset; uint64_t value;};\n")
|
||||||
|
fmt.Fprintf(w, "int num_init_pointers = %d;\n", len(info.InitPointers))
|
||||||
|
fmt.Fprintf(w, "struct init_pointer init_pointers_offsets[] = {\n")
|
||||||
|
for _, init_ptr := range info.InitPointers {
|
||||||
|
fmt.Fprintf(w, " {0x%x, 0x%x},\n", init_ptr.Offset, init_ptr.Value)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "};\n")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_lib\")))\n")
|
||||||
|
fmt.Fprintf(w, "char libs[] =\n")
|
||||||
|
for _, lib := range info.Symbols.Libs {
|
||||||
|
fmt.Fprintf(w, " \"%s\\0\"\n", lib)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ";\n")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_sym\")))\n")
|
||||||
|
fmt.Fprintf(w, "char symbols[] =\n")
|
||||||
|
for _, symbol := range info.Symbols.Symbols {
|
||||||
|
fmt.Fprintf(w, " \"%s\\0\"\n", symbol)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, ";\n")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "// very compact symbol table,\n")
|
||||||
|
fmt.Fprintf(w, "// [lib idx/*4 bytes*/, nsymbol/*4 byte*/]\n")
|
||||||
|
fmt.Fprintf(w, "// repeate nsymbol times [name offset/*3 bytes*/, segment idx/**/, offset /*4 btyes*/]\n")
|
||||||
|
fmt.Fprintf(w, "// name offset is 3 bytes because we don't think we should have a table size > 2^(3 * 8)\n")
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "__attribute__((section(\"__DATA,.bshield_code\")))\n")
|
||||||
|
fmt.Fprintf(w, "uint32_t encoded_table[] = {\n")
|
||||||
|
n_instructions := 0
|
||||||
|
for i, table := range info.Symbols.Tables {
|
||||||
|
fmt.Fprintf(w, " // %s\n", info.Symbols.Libs[i])
|
||||||
|
fmt.Fprintf(w, " %d/*lib offset*/,\n", table.LibIndex)
|
||||||
|
fmt.Fprintf(w, " %d/*nsymbols*/,\n", table.Nsymbols)
|
||||||
|
n_instructions += 2
|
||||||
|
for _, symbol := range table.Symbols {
|
||||||
|
fmt.Fprintf(w, " %d, 0x%x,\n", (symbol.SymbolIndex<<8)|symbol.SegmentIndex, symbol.Offset)
|
||||||
|
n_instructions += 2
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "};\n")
|
||||||
|
fmt.Fprintf(w, "uint32_t n_instructions = %d;\n", n_instructions)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "}// namespace bshield_data\n")
|
||||||
|
w.Flush()
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,28 @@ message MachoInfo {
|
|||||||
uint64 offset = 5; // offset in segment
|
uint64 offset = 5; // offset in segment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SymbolTable {
|
||||||
|
uint32 symbolIndex = 1;
|
||||||
|
uint32 segmentIndex = 2;
|
||||||
|
uint32 offset = 3;
|
||||||
|
}
|
||||||
|
message LibraryImportedSymbols {
|
||||||
|
uint32 libIndex = 1;
|
||||||
|
uint32 nsymbols = 2;
|
||||||
|
repeated SymbolTable symbols = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AllImportedSymbols {
|
||||||
|
repeated string libs = 1;
|
||||||
|
repeated string symbols = 2;
|
||||||
|
repeated LibraryImportedSymbols tables = 3;
|
||||||
|
}
|
||||||
|
|
||||||
PointerSize pointer_size = 1;
|
PointerSize pointer_size = 1;
|
||||||
uint64 image_base = 2;
|
uint64 image_base = 2;
|
||||||
repeated InitPointer init_pointers = 3;
|
uint64 main = 3;
|
||||||
repeated BindSymbol symbols = 4;
|
repeated InitPointer init_pointers = 4;
|
||||||
|
// repeated BindSymbol symbols = 5;
|
||||||
|
AllImportedSymbols symbols = 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "out/b.h"
|
||||||
|
|
||||||
char *pwd;
|
char *pwd;
|
||||||
uint32_t pwd_len;
|
uint32_t pwd_len;
|
||||||
|
|
||||||
@ -927,46 +929,59 @@ void fix(struct libcache& cache) {
|
|||||||
int npage_rw_fixed = 0;
|
int npage_rw_fixed = 0;
|
||||||
uint64_t page_rw_fixed[10]; // should be dynamic, but works for now
|
uint64_t page_rw_fixed[10]; // should be dynamic, but works for now
|
||||||
|
|
||||||
#include "out/b.h"
|
|
||||||
// think of a way to get what binary to fix
|
// think of a way to get what binary to fix
|
||||||
// so we can iterate through them
|
// so we can iterate through them
|
||||||
if (nimports == 0) {
|
char* lib_to_resolve = "main";
|
||||||
printf("there is no imports to fix\n");
|
|
||||||
}
|
|
||||||
struct libcache_item* libfixing = get_libcache_with_name(&cache, lib_to_resolve);
|
struct libcache_item* libfixing = get_libcache_with_name(&cache, lib_to_resolve);
|
||||||
for (int i = 0; i < nimports; i++) {
|
|
||||||
struct imported_symbol symbol = imported_table[i];
|
|
||||||
uint64_t fix_at = symbol.offset + libfixing->segment[symbol.segment_i];
|
|
||||||
|
|
||||||
int need_rw_fix = true;
|
int pc = 0;
|
||||||
for (int j = 0; j < npage_rw_fixed; j++) {
|
for (;pc != bshield_data::n_instructions;) {
|
||||||
if (page_rw_fixed[j] <= fix_at &&
|
uint32_t libidx = bshield_data::encoded_table[pc];
|
||||||
page_rw_fixed[j] + 0x1000 > fix_at) {
|
uint32_t nsym = bshield_data::encoded_table[pc + 1];
|
||||||
need_rw_fix = false;
|
pc += 2;
|
||||||
|
|
||||||
|
char* lib = bshield_data::libs + libidx;
|
||||||
|
for (int i = 0; i < nsym; i++) {
|
||||||
|
uint32_t op = bshield_data::encoded_table[pc];
|
||||||
|
uint32_t offset = bshield_data::encoded_table[pc + 1];
|
||||||
|
pc += 2;
|
||||||
|
|
||||||
|
uint32_t symidx = op >> 8;
|
||||||
|
uint32_t segment = op & 0xff;
|
||||||
|
char* sym = bshield_data::symbols + symidx;
|
||||||
|
|
||||||
|
uint64_t fix_at = offset + libfixing->segment[segment];
|
||||||
|
|
||||||
|
// enable WRITE protection for this data segment
|
||||||
|
int need_rw_fix = true;
|
||||||
|
for (int j = 0; j < npage_rw_fixed; j++) {
|
||||||
|
if (page_rw_fixed[j] <= fix_at &&
|
||||||
|
page_rw_fixed[j] + 0x1000 > fix_at) {
|
||||||
|
need_rw_fix = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (need_rw_fix) {
|
||||||
|
uint64_t start_page = fix_at - (fix_at % 0x1000);
|
||||||
|
vm_protect_func(mach_task_self_func(), start_page, 0x1000, 0,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE);
|
||||||
|
page_rw_fixed[npage_rw_fixed++] = start_page;
|
||||||
|
printf("modify page starts at 0x%llx to RW\n", start_page);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (need_rw_fix) {
|
|
||||||
uint64_t start_page = fix_at - (fix_at % 0x1000);
|
|
||||||
vm_protect_func(mach_task_self_func(), start_page, 0x1000, 0,
|
|
||||||
VM_PROT_READ | VM_PROT_WRITE);
|
|
||||||
page_rw_fixed[npage_rw_fixed++] = start_page;
|
|
||||||
printf("modify page starts at 0x%llx to RW\n", start_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *resolved;
|
void *resolved = 0;
|
||||||
// search with hash is faster
|
// search with hash is faster
|
||||||
resolved = custom_dlsym(&cache, symbol.hash, symbol.name);
|
// resolved = custom_dlsym(&cache, symbol.hash, symbol.name);
|
||||||
if (resolved == 0) {
|
if (resolved == 0) {
|
||||||
// but fuck apple they have relative path and rpath
|
// but fuck apple they have relative path and rpath
|
||||||
resolved = custom_dlsym(&cache, symbol.lib, symbol.name);
|
resolved = custom_dlsym(&cache, lib, sym);
|
||||||
}
|
}
|
||||||
*(uint64_t *)fix_at = (uint64_t)resolved;
|
*(uint64_t *)fix_at = (uint64_t)resolved;
|
||||||
|
|
||||||
printf("imports need to fix: (0x%x)%s at 0x%llx\n", symbol.hash,
|
printf("imports need to fix: %s at 0x%llx\n", sym, fix_at);
|
||||||
symbol.name, fix_at);
|
printf(" from=%s\n", lib);
|
||||||
printf(" from=%s\n", symbol.lib);
|
printf(" segment id=%d; offset=0x%llx;", segment, offset);
|
||||||
printf(" segment id=%d; offset=0x%llx;", symbol.segment_i, symbol.offset);
|
printf(" resolved=%llx(%p)\n", *(uint64_t*)fix_at, resolved);
|
||||||
printf(" resolved=%llx(%p)\n", *(uint64_t*)fix_at, resolved);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Reformat the region as per before, or leave as it
|
// TODO: Reformat the region as per before, or leave as it
|
||||||
|
@ -42,7 +42,8 @@ clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_l
|
|||||||
clang++ -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.cc
|
clang++ -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.cc
|
||||||
|
|
||||||
# extract symbols from a
|
# extract symbols from a
|
||||||
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a > $OUT/b.h
|
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a
|
||||||
|
../../macho-go/bin/ios-wrapper bcell2header -b $OUT/b.bcell -o $OUT/b.h
|
||||||
# build libb with symbols extracted from a
|
# build libb with symbols extracted from a
|
||||||
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
||||||
|
|
||||||
@ -62,7 +63,8 @@ clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_l
|
|||||||
clang -fobjc-arc -ObjC -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.mm
|
clang -fobjc-arc -ObjC -mmacosx-version-min=$VERSION -o $OUT/a -L"./out" -lb a.mm
|
||||||
|
|
||||||
# extract symbols from a
|
# extract symbols from a
|
||||||
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a > $OUT/b.h
|
../../macho-go/bin/ios-wrapper pepe -o $OUT/a-fixed -b $OUT/b.bcell --remove-imports --remove-exports --remove-symbol-table $OUT/a
|
||||||
|
../../macho-go/bin/ios-wrapper bcell2header -b $OUT/b.bcell -o $OUT/b.h
|
||||||
# build libb with symbols extracted from a
|
# build libb with symbols extracted from a
|
||||||
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
clang++ -mmacosx-version-min=$VERSION -o $OUT/libb.dylib -shared -Wl,-reexport_library out/libc.dylib b.cc
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user