]>
git.saurik.com Git - apple/ld64.git/blob - src/Readers/ObjectFileArchiveMachO.cpp
a6851a1d3e537a5ee83647d926c7fd3b6084670c
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 namespace ObjectFileArchiveMachO
{
28 class Reader
: public ObjectFile::Reader
31 Reader(const uint8_t fileContent
[], uint64_t fileLength
, const char* path
, const ObjectFile::ReaderOptions
& options
);
34 virtual const char* getPath();
35 virtual std::vector
<class ObjectFile::Atom
*>& getAtoms();
36 virtual std::vector
<class ObjectFile::Atom
*>* getJustInTimeAtomsFor(const char* name
);
37 virtual std::vector
<ObjectFile::StabsInfo
>* getStabsDebugInfo();
43 const char* getName() const;
44 const uint8_t* getContent() const;
45 uint32_t getContentSize() const;
46 const Entry
* getNext() const;
48 bool hasLongName() const;
49 unsigned int getLongNameSpace() const;
53 const struct ranlib
* ranlibBinarySearch(const char* name
);
54 const struct ranlib
* ranlibLinearSearch(const char* name
);
55 ObjectFile::Reader
* makeObjectReaderForMember(const Entry
* member
);
56 void dumpTableOfContents();
59 const ObjectFile::ReaderOptions
& fOptions
;
60 const uint8_t* fFileContent
;
62 const struct ranlib
* fTableOfContents
;
63 uint32_t fTableOfContentCount
;
65 const char* fStringPool
;
66 std::vector
<class ObjectFile::Atom
*> fAllAtoms
;
67 std::set
<const class Entry
*> fInstantiatedEntries
;
69 static std::vector
<class ObjectFile::Atom
*> fgEmptyList
;
72 std::vector
<class ObjectFile::Atom
*> Reader::fgEmptyList
;
75 bool Reader::Entry::hasLongName() const
77 return ( strncmp(this->ar_name
, AR_EFMT1
, strlen(AR_EFMT1
)) == 0 );
80 unsigned int Reader::Entry::getLongNameSpace() const
83 long result
= strtol(&this->ar_name
[strlen(AR_EFMT1
)], &endptr
, 10);
87 const char* Reader::Entry::getName() const
89 if ( this->hasLongName() ) {
90 int len
= this->getLongNameSpace();
91 static char longName
[256];
92 strncpy(longName
, ((char*)this)+sizeof(ar_hdr
), len
);
97 static char shortName
[20];
98 strncpy(shortName
, this->ar_name
, 16);
100 char* space
= strchr(shortName
, ' ');
108 const uint8_t* Reader::Entry::getContent() const
110 if ( this->hasLongName() )
111 return ((uint8_t*)this) + sizeof(ar_hdr
) + this->getLongNameSpace();
113 return ((uint8_t*)this) + sizeof(ar_hdr
);
117 uint32_t Reader::Entry::getContentSize() const
120 strncpy(temp
, this->ar_size
, 10);
123 long size
= strtol(temp
, &endptr
, 10);
124 // long name is included in ar_size
125 if ( this->hasLongName() )
126 size
-= this->getLongNameSpace();
130 const Reader::Entry
* Reader::Entry::getNext() const
132 const uint8_t* p
= this->getContent() + getContentSize();
133 p
= (const uint8_t*)(((uint32_t)p
+3) & (-4)); // 4-byte align
134 return (Reader::Entry
*)p
;
139 Reader::Reader(const uint8_t fileContent
[], uint64_t fileLength
, const char* path
, const ObjectFile::ReaderOptions
& options
)
140 : fPath(NULL
), fOptions(options
), fFileContent(NULL
), fTableOfContents(NULL
), fTableOfContentCount(0),
141 fSorted(false), fStringPool(NULL
)
143 fPath
= strdup(path
);
144 fFileContent
= fileContent
;
145 fFileLength
= fileLength
;
147 if ( strncmp((const char*)fileContent
, "!<arch>\n", 8) != 0 )
148 throw "not an archive";
150 if ( !options
.fFullyLoadArchives
) {
151 const Entry
* const firstMember
= (Entry
*)&fFileContent
[8];
152 if ( strcmp(firstMember
->getName(), SYMDEF_SORTED
) == 0 )
154 else if ( strcmp(firstMember
->getName(), SYMDEF
) == 0 )
157 throw "archive has no table of contents";
158 const uint8_t* contents
= firstMember
->getContent();
159 uint32_t ranlibArrayLen
= OSReadBigInt32((void *) contents
, 0);
160 fTableOfContents
= (const struct ranlib
*)&contents
[4];
161 fTableOfContentCount
= ranlibArrayLen
/ sizeof(struct ranlib
);
162 fStringPool
= (const char*)&contents
[ranlibArrayLen
+8];
165 if ( options
.fTraceArchives
)
166 printf("[Logging for Build & Integration] Used static archive: %s\n", fPath
);
175 ObjectFile::Reader
* Reader::makeObjectReaderForMember(const Entry
* member
)
177 const char* memberName
= member
->getName();
178 char memberPath
[strlen(fPath
) + strlen(memberName
)+4];
179 strcpy(memberPath
, fPath
);
180 strcat(memberPath
, "(");
181 strcat(memberPath
, memberName
);
182 strcat(memberPath
, ")");
183 //fprintf(stderr, "using %s from %s\n", memberName, fPath);
185 return ObjectFileMachO::MakeReader((class macho_header
*)member
->getContent(), memberPath
, fOptions
);
187 catch (const char* msg
) {
188 throwf("in %s, %s", memberPath
, msg
);
192 const char* Reader::getPath()
197 std::vector
<class ObjectFile::Atom
*>& Reader::getAtoms()
199 if ( fOptions
.fFullyLoadArchives
) {
200 // build vector of all atoms from all .o files in this archive
201 const Entry
* const start
= (Entry
*)&fFileContent
[8];
202 const Entry
* const end
= (Entry
*)&fFileContent
[fFileLength
];
203 for (const Entry
* p
=start
; p
< end
; p
= p
->getNext()) {
204 const char* memberName
= p
->getName();
205 if ( (p
==start
) && (strcmp(memberName
, SYMDEF_SORTED
) == 0) )
207 ObjectFile::Reader
* r
= this->makeObjectReaderForMember(p
);
208 std::vector
<class ObjectFile::Atom
*>& atoms
= r
->getAtoms();
209 fAllAtoms
.insert(fAllAtoms
.end(), atoms
.begin(), atoms
.end());
214 // return nonthing for now, getJustInTimeAtomsFor() will return atoms as needed
220 const struct ranlib
* Reader::ranlibBinarySearch(const char* key
)
222 const struct ranlib
* base
= fTableOfContents
;
223 for (uint32_t n
= fTableOfContentCount
; n
> 0; n
/= 2) {
224 const struct ranlib
* pivot
= &base
[n
/2];
225 const char* pivotStr
= &fStringPool
[OSSwapBigToHostInt32(pivot
->ran_un
.ran_strx
)];
226 int cmp
= strcmp(key
, pivotStr
);
231 // move base to symbol after pivot
243 const struct ranlib
* Reader::ranlibLinearSearch(const char* key
)
245 for (uint32_t i
= 0; i
< fTableOfContentCount
; ++i
) {
246 const struct ranlib
* entry
= &fTableOfContents
[i
];
247 const char* entryName
= &fStringPool
[OSSwapBigToHostInt32(entry
->ran_un
.ran_strx
)];
248 if ( strcmp(key
, entryName
) == 0 )
255 void Reader::dumpTableOfContents()
257 for (unsigned int i
=0; i
< fTableOfContentCount
; ++i
) {
258 const struct ranlib
* e
= &fTableOfContents
[i
];
259 printf("%s in %s\n", &fStringPool
[OSSwapBigToHostInt32(e
->ran_un
.ran_strx
)], ((Entry
*)&fFileContent
[OSSwapBigToHostInt32(e
->ran_off
)])->getName());
263 std::vector
<class ObjectFile::Atom
*>* Reader::getJustInTimeAtomsFor(const char* name
)
265 if ( fOptions
.fFullyLoadArchives
) {
269 const struct ranlib
* result
= NULL
;
271 // do a binary search of table of contents lookig for requested symbol
272 result
= ranlibBinarySearch(name
);
275 // do a linear search of table of contents lookig for requested symbol
276 result
= ranlibLinearSearch(name
);
278 if ( result
!= NULL
) {
279 const Entry
* member
= (Entry
*)&fFileContent
[OSSwapBigToHostInt32(result
->ran_off
)];
280 //fprintf(stderr, "%s found in %s\n", name, member->getName());
281 if ( fInstantiatedEntries
.count(member
) == 0 ) {
282 // only return these atoms once
283 fInstantiatedEntries
.insert(member
);
284 ObjectFile::Reader
* r
= makeObjectReaderForMember(member
);
285 return new std::vector
<class ObjectFile::Atom
*>(r
->getAtoms());
288 //fprintf(stderr, "%s NOT found in archive %s\n", name, fPath);
294 std::vector
<ObjectFile::StabsInfo
>* Reader::getStabsDebugInfo()
301 Reader
* MakeReader(const uint8_t fileContent
[], uint64_t fileLength
, const char* path
, const ObjectFile::ReaderOptions
& options
)
303 return new Reader(fileContent
, fileLength
, path
, options
);