[cfe-commits] r45122 - in /cfe/trunk: Lex/HeaderMap.cpp include/clang/Lex/HeaderMap.h
Chris Lattner
sabre at nondot.org
Mon Dec 17 13:06:12 PST 2007
Author: lattner
Date: Mon Dec 17 15:06:11 2007
New Revision: 45122
URL: http://llvm.org/viewvc/llvm-project?rev=45122&view=rev
Log:
implement enough helper functions to successfully dump out the
contents of the header map. Look ma, no assumptions about input data
here (aka, corrupt header maps can't crash the compiler - crazy thought).
Modified:
cfe/trunk/Lex/HeaderMap.cpp
cfe/trunk/include/clang/Lex/HeaderMap.h
Modified: cfe/trunk/Lex/HeaderMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/HeaderMap.cpp?rev=45122&r1=45121&r2=45122&view=diff
==============================================================================
--- cfe/trunk/Lex/HeaderMap.cpp (original)
+++ cfe/trunk/Lex/HeaderMap.cpp Mon Dec 17 15:06:11 2007
@@ -19,9 +19,23 @@
#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
+//===----------------------------------------------------------------------===//
+// Data Structures and Manifest Constants
+//===----------------------------------------------------------------------===//
+
enum {
- HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p',
- HeaderVersion = 1
+ HMAP_HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p',
+ HMAP_HeaderVersion = 1,
+
+ HMAP_EmptyBucketKey = 0
+};
+
+namespace clang {
+struct HMapBucket {
+ uint32_t Key; // Offset (into strings) of key.
+
+ uint32_t Prefix; // Offset (into strings) of value prefix.
+ uint32_t Suffix; // Offset (into strings) of value suffix.
};
struct HMapHeader {
@@ -29,12 +43,17 @@
uint16_t Version; // Version number -- currently 1.
uint16_t Reserved; // Reserved for future use - zero for now.
uint32_t StringsOffset; // Offset to start of string pool.
- uint32_t Count; // Number of entries in the string table.
- uint32_t Capacity; // Number of buckets (always a power of 2).
+ uint32_t NumEntries; // Number of entries in the string table.
+ uint32_t NumBuckets; // Number of buckets (always a power of 2).
uint32_t MaxValueLength; // Length of longest result path (excluding nul).
+ // An array of 'NumBuckets' HMapBucket objects follows this header.
// Strings follow the buckets, at StringsOffset.
};
+} // end namespace clang.
+//===----------------------------------------------------------------------===//
+// Verification and Construction
+//===----------------------------------------------------------------------===//
/// HeaderMap::Create - This attempts to load the specified file as a header
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
@@ -57,10 +76,11 @@
// Sniff it to see if it's a headermap by checking the magic number and
// version.
bool NeedsByteSwap;
- if (Header->Magic == HeaderMagicNumber && Header->Version == HeaderVersion)
+ if (Header->Magic == HMAP_HeaderMagicNumber &&
+ Header->Version == HMAP_HeaderVersion)
NeedsByteSwap = false;
- else if (Header->Magic == llvm::ByteSwap_32(HeaderMagicNumber) &&
- Header->Version == llvm::ByteSwap_16(HeaderVersion))
+ else if (Header->Magic == llvm::ByteSwap_32(HMAP_HeaderMagicNumber) &&
+ Header->Version == llvm::ByteSwap_16(HMAP_HeaderVersion))
NeedsByteSwap = true; // Mixed endianness headermap.
else
return 0; // Not a header map.
@@ -75,12 +95,90 @@
delete FileBuffer;
}
+//===----------------------------------------------------------------------===//
+// Utility Methods
+//===----------------------------------------------------------------------===//
+
/// getFileName - Return the filename of the headermap.
const char *HeaderMap::getFileName() const {
return FileBuffer->getBufferIdentifier();
}
+unsigned HeaderMap::getEndianAdjustedWord(unsigned X) const {
+ if (!NeedsBSwap) return X;
+ return llvm::ByteSwap_32(X);
+}
+
+/// getHeader - Return a reference to the file header, in unbyte-swapped form.
+/// This method cannot fail.
+const HMapHeader &HeaderMap::getHeader() const {
+ // We know the file is at least as big as the header. Return it.
+ return *reinterpret_cast<const HMapHeader*>(FileBuffer->getBufferStart());
+}
+
+/// getBucket - Return the specified hash table bucket from the header map,
+/// bswap'ing its fields as appropriate. If the bucket number is not valid,
+/// this return a bucket with an empty key (0).
+HMapBucket HeaderMap::getBucket(unsigned BucketNo) const {
+ HMapBucket Result;
+ Result.Key = HMAP_EmptyBucketKey;
+
+ const HMapBucket *BucketArray =
+ reinterpret_cast<const HMapBucket*>(FileBuffer->getBufferStart() +
+ sizeof(HMapHeader));
+
+ const HMapBucket *BucketPtr = BucketArray+BucketNo;
+ if ((char*)(BucketPtr+1) > FileBuffer->getBufferEnd())
+ return Result; // Invalid buffer, corrupt hmap.
+
+ // Otherwise, the bucket is valid. Load the values, bswapping as needed.
+ Result.Key = getEndianAdjustedWord(BucketPtr->Key);
+ Result.Prefix = getEndianAdjustedWord(BucketPtr->Prefix);
+ Result.Suffix = getEndianAdjustedWord(BucketPtr->Suffix);
+ return Result;
+}
+
+/// getString - Look up the specified string in the string table. If the string
+/// index is not valid, it returns an empty string.
+const char *HeaderMap::getString(unsigned StrTabIdx) const {
+ // Add the start of the string table to the idx.
+ StrTabIdx += getEndianAdjustedWord(getHeader().StringsOffset);
+
+ // Check for invalid index.
+ if (StrTabIdx >= FileBuffer->getBufferSize())
+ return 0;
+
+ // Otherwise, we have a valid pointer into the file. Just return it. We know
+ // that the "string" can not overrun the end of the file, because the buffer
+ // is nul terminated by virtue of being a MemoryBuffer.
+ return FileBuffer->getBufferStart()+StrTabIdx;
+}
+
+//===----------------------------------------------------------------------===//
+// The Main Drivers
+//===----------------------------------------------------------------------===//
+
+/// dump - Print the contents of this headermap to stderr.
+void HeaderMap::dump() const {
+ const HMapHeader &Hdr = getHeader();
+ unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
+
+ fprintf(stderr, "Header Map %s:\n %d buckets, %d entries\n",
+ getFileName(), NumBuckets,
+ getEndianAdjustedWord(Hdr.NumEntries));
+
+ for (unsigned i = 0; i != NumBuckets; ++i) {
+ HMapBucket B = getBucket(i);
+ if (B.Key == HMAP_EmptyBucketKey) continue;
+
+ const char *Key = getString(B.Key);
+ const char *Prefix = getString(B.Prefix);
+ const char *Suffix = getString(B.Suffix);
+ fprintf(stderr, " %d. %s -> '%s' '%s'\n", i, Key, Prefix, Suffix);
+ }
+}
+
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
const FileEntry *HeaderMap::LookupFile(const char *FilenameStart,
Modified: cfe/trunk/include/clang/Lex/HeaderMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderMap.h?rev=45122&r1=45121&r2=45122&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderMap.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderMap.h Mon Dec 17 15:06:11 2007
@@ -20,6 +20,8 @@
namespace clang {
class FileEntry;
class FileManager;
+ struct HMapBucket;
+ struct HMapHeader;
/// This class represents an Apple concept known as a 'header map'. To the
/// #include file resolution process, it basically acts like a directory of
@@ -49,6 +51,15 @@
/// getFileName - Return the filename of the headermap.
const char *getFileName() const;
+
+ /// dump - Print the contents of this headermap to stderr.
+ void dump() const;
+
+private:
+ unsigned getEndianAdjustedWord(unsigned X) const;
+ const HMapHeader &getHeader() const;
+ HMapBucket getBucket(unsigned BucketNo) const;
+ const char *getString(unsigned StrTabIdx) const;
};
} // end namespace clang.
More information about the cfe-commits
mailing list