mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
<rdar://problem/6927148> libLTO needs to handle i386 magic objc class symbols
Parse __OBJC data structures and synthesize magic .objc_ symbols. Also, alter mangler so that objc method names are readable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72700 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8fff19ba55
commit
3eb445feb2
@ -14,6 +14,7 @@
|
||||
|
||||
#include "LTOModule.h"
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/ModuleProvider.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@ -176,11 +177,123 @@ void LTOModule::addDefinedFunctionSymbol(Function* f, Mangler &mangler)
|
||||
}
|
||||
}
|
||||
|
||||
void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler)
|
||||
// get string that data pointer points to
|
||||
bool LTOModule::objcClassNameFromExpression(Constant* c, std::string& name)
|
||||
{
|
||||
if (ConstantExpr* ce = dyn_cast<ConstantExpr>(c)) {
|
||||
Constant* op = ce->getOperand(0);
|
||||
if (GlobalVariable* gvn = dyn_cast<GlobalVariable>(op)) {
|
||||
Constant* cn = gvn->getInitializer();
|
||||
if (ConstantArray* ca = dyn_cast<ConstantArray>(cn)) {
|
||||
if ( ca->isCString() ) {
|
||||
name = ".objc_class_name_" + ca->getAsString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse i386/ppc ObjC class data structure
|
||||
void LTOModule::addObjCClass(GlobalVariable* clgv)
|
||||
{
|
||||
if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
|
||||
// second slot in __OBJC,__class is pointer to superclass name
|
||||
std::string superclassName;
|
||||
if ( objcClassNameFromExpression(c->getOperand(1), superclassName) ) {
|
||||
NameAndAttributes info;
|
||||
if ( _undefines.find(superclassName.c_str()) == _undefines.end() ) {
|
||||
const char* symbolName = ::strdup(superclassName.c_str());
|
||||
info.name = ::strdup(symbolName);
|
||||
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||
// string is owned by _undefines
|
||||
_undefines[info.name] = info;
|
||||
}
|
||||
}
|
||||
// third slot in __OBJC,__class is pointer to class name
|
||||
std::string className;
|
||||
if ( objcClassNameFromExpression(c->getOperand(2), className) ) {
|
||||
const char* symbolName = ::strdup(className.c_str());
|
||||
NameAndAttributes info;
|
||||
info.name = symbolName;
|
||||
info.attributes = (lto_symbol_attributes)
|
||||
(LTO_SYMBOL_PERMISSIONS_DATA |
|
||||
LTO_SYMBOL_DEFINITION_REGULAR |
|
||||
LTO_SYMBOL_SCOPE_DEFAULT);
|
||||
_symbols.push_back(info);
|
||||
_defines[info.name] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parse i386/ppc ObjC category data structure
|
||||
void LTOModule::addObjCCategory(GlobalVariable* clgv)
|
||||
{
|
||||
if (ConstantStruct* c = dyn_cast<ConstantStruct>(clgv->getInitializer())) {
|
||||
// second slot in __OBJC,__category is pointer to target class name
|
||||
std::string targetclassName;
|
||||
if ( objcClassNameFromExpression(c->getOperand(1), targetclassName) ) {
|
||||
NameAndAttributes info;
|
||||
if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ){
|
||||
const char* symbolName = ::strdup(targetclassName.c_str());
|
||||
info.name = ::strdup(symbolName);
|
||||
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||
// string is owned by _undefines
|
||||
_undefines[info.name] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parse i386/ppc ObjC class list data structure
|
||||
void LTOModule::addObjCClassRef(GlobalVariable* clgv)
|
||||
{
|
||||
std::string targetclassName;
|
||||
if ( objcClassNameFromExpression(clgv->getInitializer(), targetclassName) ){
|
||||
NameAndAttributes info;
|
||||
if ( _undefines.find(targetclassName.c_str()) == _undefines.end() ) {
|
||||
const char* symbolName = ::strdup(targetclassName.c_str());
|
||||
info.name = ::strdup(symbolName);
|
||||
info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
|
||||
// string is owned by _undefines
|
||||
_undefines[info.name] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler& mangler)
|
||||
{
|
||||
// add to list of defined symbols
|
||||
addDefinedSymbol(v, mangler, false);
|
||||
|
||||
// special case i386/ppc ObjC data structures in magic sections
|
||||
if ( v->hasSection() ) {
|
||||
// special case if this data blob is an ObjC class definition
|
||||
if ( v->getSection().compare(0, 15, "__OBJC,__class,") == 0 ) {
|
||||
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||
addObjCClass(gv);
|
||||
}
|
||||
}
|
||||
|
||||
// special case if this data blob is an ObjC category definition
|
||||
else if ( v->getSection().compare(0, 18, "__OBJC,__category,") == 0 ) {
|
||||
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||
addObjCCategory(gv);
|
||||
}
|
||||
}
|
||||
|
||||
// special case if this data blob is the list of referenced classes
|
||||
else if ( v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0 ) {
|
||||
if (GlobalVariable* gv = dyn_cast<GlobalVariable>(v)) {
|
||||
addObjCClassRef(gv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add external symbols referenced by this data.
|
||||
for (unsigned count = 0, total = v->getNumOperands();
|
||||
count != total; ++count) {
|
||||
@ -192,9 +305,13 @@ void LTOModule::addDefinedDataSymbol(GlobalValue* v, Mangler &mangler)
|
||||
void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
|
||||
bool isFunction)
|
||||
{
|
||||
// ignore all llvm.* symbols
|
||||
if ( strncmp(def->getNameStart(), "llvm.", 5) == 0 )
|
||||
return;
|
||||
|
||||
// string is owned by _defines
|
||||
const char* symbolName = ::strdup(mangler.getValueName(def).c_str());
|
||||
|
||||
|
||||
// set alignment part log2() can have rounding errors
|
||||
uint32_t align = def->getAlignment();
|
||||
uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
|
||||
@ -241,25 +358,28 @@ void LTOModule::addDefinedSymbol(GlobalValue* def, Mangler &mangler,
|
||||
}
|
||||
|
||||
void LTOModule::addAsmGlobalSymbol(const char *name) {
|
||||
// string is owned by _defines
|
||||
const char *symbolName = ::strdup(name);
|
||||
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
||||
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
||||
|
||||
// add to table of symbols
|
||||
NameAndAttributes info;
|
||||
info.name = symbolName;
|
||||
info.attributes = (lto_symbol_attributes)attr;
|
||||
_symbols.push_back(info);
|
||||
_defines[info.name] = 1;
|
||||
// only add new define if not already defined
|
||||
if ( _defines.count(name, &name[strlen(name)+1]) == 0 )
|
||||
return;
|
||||
|
||||
// string is owned by _defines
|
||||
const char *symbolName = ::strdup(name);
|
||||
uint32_t attr = LTO_SYMBOL_DEFINITION_REGULAR;
|
||||
attr |= LTO_SYMBOL_SCOPE_DEFAULT;
|
||||
NameAndAttributes info;
|
||||
info.name = symbolName;
|
||||
info.attributes = (lto_symbol_attributes)attr;
|
||||
_symbols.push_back(info);
|
||||
_defines[info.name] = 1;
|
||||
}
|
||||
|
||||
void LTOModule::addPotentialUndefinedSymbol(GlobalValue* decl, Mangler &mangler)
|
||||
{
|
||||
const char* name = mangler.getValueName(decl).c_str();
|
||||
// ignore all llvm.* symbols
|
||||
if ( strncmp(name, "llvm.", 5) == 0 )
|
||||
return;
|
||||
if ( strncmp(decl->getNameStart(), "llvm.", 5) == 0 )
|
||||
return;
|
||||
|
||||
const char* name = mangler.getValueName(decl).c_str();
|
||||
|
||||
// we already have the symbol
|
||||
if (_undefines.find(name) != _undefines.end())
|
||||
@ -306,6 +426,14 @@ void LTOModule::lazyParseSymbols()
|
||||
|
||||
// Use mangler to add GlobalPrefix to names to match linker names.
|
||||
Mangler mangler(*_module, _target->getTargetAsmInfo()->getGlobalPrefix());
|
||||
// add chars used in ObjC method names so method names aren't mangled
|
||||
mangler.markCharAcceptable('[');
|
||||
mangler.markCharAcceptable(']');
|
||||
mangler.markCharAcceptable('(');
|
||||
mangler.markCharAcceptable(')');
|
||||
mangler.markCharAcceptable('-');
|
||||
mangler.markCharAcceptable('+');
|
||||
mangler.markCharAcceptable(' ');
|
||||
|
||||
// add functions
|
||||
for (Module::iterator f = _module->begin(); f != _module->end(); ++f) {
|
||||
|
@ -77,13 +77,19 @@ private:
|
||||
void addDefinedDataSymbol(llvm::GlobalValue* v,
|
||||
llvm::Mangler &mangler);
|
||||
void addAsmGlobalSymbol(const char *);
|
||||
void addObjCClass(llvm::GlobalVariable* clgv);
|
||||
void addObjCCategory(llvm::GlobalVariable* clgv);
|
||||
void addObjCClassRef(llvm::GlobalVariable* clgv);
|
||||
bool objcClassNameFromExpression(llvm::Constant* c,
|
||||
std::string& name);
|
||||
|
||||
static bool isTargetMatch(llvm::MemoryBuffer* memBuffer,
|
||||
const char* triplePrefix);
|
||||
|
||||
|
||||
static LTOModule* makeLTOModule(llvm::MemoryBuffer* buffer,
|
||||
std::string& errMsg);
|
||||
static llvm::MemoryBuffer* makeBuffer(const void* mem, size_t length);
|
||||
|
||||
|
||||
typedef llvm::StringMap<uint8_t> StringSet;
|
||||
|
||||
struct NameAndAttributes {
|
||||
|
Loading…
Reference in New Issue
Block a user