我试图在C ++下编译OS X上的一些代码,但是我遇到了一些未找到符号的问题。
当我为C编译时,它的工作正常:
g++ -x c -fobjc-arc -fobjc-link-runtime -framework IOKit -framework CoreFoundation -framework Foundation kextstat/main.cpp -o ks
当我将-x c
更改为-x c++
时,突然找不到符号:
$ g++ -x c++ -fobjc-arc -fobjc-link-runtime -framework IOKit -framework CoreFoundation -framework Foundation kextstat/main.cpp -o ks
Undefined symbols for architecture x86_64:
"OSKextCopyLoadedKextInfo(__CFArray const*, __CFArray const*)", referenced from:
_main in main-66ed7f.o
"kas_info(int, void*, unsigned long*)", referenced from:
print_kextstat(__CFDictionary const*) in main-66ed7f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我删除了对这些符号的引用并编译了C ++版本,以便我可以查看每个二进制文件链接的库,看看是否存在不一致,但它们完全相同:
$ otool -L ks_cxx
ks_cxx:
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.17.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1056.13.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
$ otool -L ks_c
ks_c:
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.17.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1056.13.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
这是main.cpp
的代码清单:
#import <CoreFoundation/CoreFoundation.h>
#define KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR (0)
#define KAS_INFO_MAX_SELECTOR (1)
int kas_info(int selector, void *value, size_t *size);
extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
// Convert a CFString to a standard C string
char* cstring(CFStringRef s) {
return ((char*)CFStringGetCStringPtr(s, kCFStringEncodingMacRoman));
}
void print_kextstat(CFDictionaryRef dict) {
size_t kaslr_size = 0;
uint64_t kaslr_slide = 0;
kaslr_size = sizeof(kaslr_slide);
int ret = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &kaslr_slide, &kaslr_size);
if (ret != 0) {
printf("[ERROR] Could not get kernel ASLR slide info from kas_info(). Errno: %d\n", errno);
exit(1);
}
printf("[INFO] Kernel ASLR slide is 0x%llx\n", kaslr_slide);
CFIndex count = CFDictionaryGetCount(dict);
CFIndex i, j;
void **keys;
void **values;
keys = (void **)malloc(sizeof(void *) * count);
values = (void **)malloc(sizeof(void *) * count);
CFDictionaryGetKeysAndValues(
dict,
(const void **)keys,
(const void **)values
);
printf("Index Refs Address Size Wired Name (Version) <Linked Against>\n");
for (i = 0; i < count; i++) {
for (j = 0; j < count; j++) {
int kextTag;
int refs;
unsigned long long address;
unsigned long long size;
unsigned long long wired;
char *name = cstring((CFStringRef)CFDictionaryGetValue((CFDictionaryRef)(values)[j], CFSTR("CFBundleIdentifier")));
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadTag")),
kCFNumberSInt32Type,
&kextTag
);
if (kextTag != i) {
continue;
}
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleRetainCount")),
kCFNumberSInt32Type,
&refs
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadAddress")),
kCFNumberSInt64Type,
&address
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleLoadSize")),
kCFNumberSInt64Type,
&size
);
CFNumberGetValue(
(CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("OSBundleWiredSize")),
kCFNumberSInt64Type,
&wired
);
printf("%5d %4d 0x%-16llx 0x%-10llx 0x%-10llx %s (%s) ",
kextTag,
refs,
address + kaslr_slide,
size,
wired,
name,
cstring((CFStringRef)CFDictionaryGetValue((CFDictionaryRef)values[j], CFSTR("CFBundleVersion")))
);
CFArrayRef linkedAgainst = (CFArrayRef)CFDictionaryGetValue(
(CFDictionaryRef)values[j],
CFSTR("OSBundleDependencies")
);
if (linkedAgainst == NULL) {
printf("\n");
continue;
}
CFIndex linkedCount = CFArrayGetCount(linkedAgainst);
int linked = 0;
CFMutableArrayRef marray = CFArrayCreateMutableCopy(
NULL,
linkedCount,
linkedAgainst
);
CFArraySortValues(
marray,
CFRangeMake(0, linkedCount),
(CFComparatorFunction)CFNumberCompare,
NULL
);
printf("<");
int l;
for (l = 0; l < linkedCount; l++) {
CFNumberGetValue(
(CFNumberRef)CFArrayGetValueAtIndex(marray, l),
kCFNumberSInt32Type,
&linked
);
if (l) {
printf(" ");
}
printf ("%d", linked);
}
printf(">\n");
}
}
}
int main (int argc, char **argv) {
if (getuid() != 0) {
printf("[ERROR] Please run me as root!\n");
exit(1);
}
print_kextstat(OSKextCopyLoadedKextInfo(NULL, NULL));
}
答案 0 :(得分:0)
对于与使用C ABI编译的代码(而不是C ++ ABI)链接的符号,需要extern "C"
:
extern "C" {
int kas_info(int selector, void *value, size_t *size);
CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
}
如果需要使用C和C ++编译程序:
#ifdef __cplusplus
#define EXTERN_C_BEG extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEG
#define EXTERN_C_END
#endif
EXTERN_C_BEG
int kas_info(int selector, void *value, size_t *size);
CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
EXTERN_C_END