Archive.cpp revision 1fce09125cb46c91407668ca29915c450a482811
1//===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Reid Spencer and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the implementation of the Archive and ArchiveMember
11// classes that is common to both reading and writing archives..
12//
13//===----------------------------------------------------------------------===//
14
15#include "ArchiveInternals.h"
16#include "llvm/ModuleProvider.h"
17
18using namespace llvm;
19
20// getMemberSize - compute the actual physical size of the file member as seen
21// on disk. This isn't the size of member's payload. Use getSize() for that.
22unsigned
23ArchiveMember::getMemberSize() const {
24  // Basically its the file size plus the header size
25  unsigned result =  info.fileSize + sizeof(ArchiveMemberHeader);
26
27  // If it has a long filename, include the name length
28  if (hasLongFilename())
29    result += path.toString().length() + 1;
30
31  // If its now odd lengthed, include the padding byte
32  if (result % 2 != 0 )
33    result++;
34
35  return result;
36}
37
38// This default constructor is only use by the ilist when it creates its
39// sentry node. We give it specific static values to make it stand out a bit.
40ArchiveMember::ArchiveMember()
41  : next(0), prev(0), parent(0), path("<invalid>"), flags(0), data(0)
42{
43  info.user = 1000;
44  info.group = 1000;
45  info.mode = 0777;
46  info.fileSize = 0;
47  info.modTime = sys::TimeValue::now();
48}
49
50// This is the constructor that the Archive class uses when it is building or
51// reading an archive. It just defaults a few things and ensures the parent is
52// set for the iplist. The Archive class fills in the ArchiveMember's data.
53// This is required because correctly setting the data may depend on other
54// things in the Archive.
55ArchiveMember::ArchiveMember(Archive* PAR)
56  : next(0), prev(0), parent(PAR), path(), flags(0), data(0)
57{
58}
59
60// This method allows an ArchiveMember to be replaced with the data for a
61// different file, presumably as an update to the member. It also makes sure
62// the flags are reset correctly.
63void ArchiveMember::replaceWith(const sys::Path& newFile) {
64  assert(newFile.exists() && "Can't replace with a non-existent file");
65  data = 0;
66  path = newFile;
67
68  // SVR4 symbol tables have an empty name
69  if (path.toString() == ARFILE_SVR4_SYMTAB_NAME)
70    flags |= SVR4SymbolTableFlag;
71  else
72    flags &= ~SVR4SymbolTableFlag;
73
74  // BSD4.4 symbol tables have a special name
75  if (path.toString() == ARFILE_BSD4_SYMTAB_NAME)
76    flags |= BSD4SymbolTableFlag;
77  else
78    flags &= ~BSD4SymbolTableFlag;
79
80  // LLVM symbol tables have a very specific name
81  if (path.toString() == ARFILE_LLVM_SYMTAB_NAME)
82    flags |= LLVMSymbolTableFlag;
83  else
84    flags &= ~LLVMSymbolTableFlag;
85
86  // String table name
87  if (path.toString() == ARFILE_STRTAB_NAME)
88    flags |= StringTableFlag;
89  else
90    flags &= ~StringTableFlag;
91
92  // If it has a slash then it has a path
93  bool hasSlash = path.toString().find('/') != std::string::npos;
94  if (hasSlash)
95    flags |= HasPathFlag;
96  else
97    flags &= ~HasPathFlag;
98
99  // If it has a slash or its over 15 chars then its a long filename format
100  if (hasSlash || path.toString().length() > 15)
101    flags |= HasLongFilenameFlag;
102  else
103    flags &= ~HasLongFilenameFlag;
104
105  // Get the signature and status info
106  std::string magic;
107  const char* signature = (const char*) data;
108  if (!signature) {
109    path.getMagicNumber(magic,4);
110    signature = magic.c_str();
111    path.getStatusInfo(info);
112  }
113
114  // Determine what kind of file it is
115  switch (sys::IdentifyFileType(signature,4)) {
116    case sys::BytecodeFileType:
117      flags |= BytecodeFlag;
118      break;
119    case sys::CompressedBytecodeFileType:
120      flags |= CompressedBytecodeFlag;
121      flags &= ~CompressedFlag;
122      break;
123    default:
124      flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
125      break;
126  }
127}
128
129// Archive constructor - this is the only constructor that gets used for the
130// Archive class. Everything else (default,copy) is deprecated. This just
131// initializes and maps the file into memory, if requested.
132Archive::Archive(const sys::Path& filename, bool map )
133  : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
134    symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
135{
136  if (map) {
137    mapfile = new sys::MappedFile(filename);
138    base = (char*) mapfile->map();
139  }
140}
141
142// Archive destructor - just clean up memory
143Archive::~Archive() {
144  // Shutdown the file mapping
145  if (mapfile) {
146    mapfile->unmap();
147    delete mapfile;
148  }
149  // Delete any ModuleProviders and ArchiveMember's we've allocated as a result
150  // of symbol table searches.
151  for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) {
152    delete I->second.first;
153    delete I->second.second;
154  }
155}
156
157// vim: sw=2 ai
158