1 // archive.h -- archive support for gold -*- C++ -*- 2 3 // Copyright 2006, 2007, 2008 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant@google.com>. 5 6 // This file is part of gold. 7 8 // This program is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 3 of the License, or 11 // (at your option) any later version. 12 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 // MA 02110-1301, USA. 22 23 #ifndef GOLD_ARCHIVE_H 24 #define GOLD_ARCHIVE_H 25 26 #include <string> 27 #include <vector> 28 29 #include "fileread.h" 30 #include "workqueue.h" 31 32 namespace gold 33 { 34 35 class Task; 36 class Input_file; 37 class Input_objects; 38 class Input_group; 39 class Layout; 40 class Symbol_table; 41 class Object; 42 class Read_symbols_data; 43 44 // This class represents an archive--generally a libNAME.a file. 45 // Archives have a symbol table and a list of objects. 46 47 class Archive 48 { 49 public: 50 Archive(const std::string& name, Input_file* input_file, 51 bool is_thin_archive, Dirsearch* dirpath, Task* task) 52 : name_(name), input_file_(input_file), armap_(), armap_names_(), 53 extended_names_(), armap_checked_(), seen_offsets_(), members_(), 54 is_thin_archive_(is_thin_archive), nested_archives_(), 55 dirpath_(dirpath), task_(task), num_members_(0) 56 { } 57 58 // The length of the magic string at the start of an archive. 59 static const int sarmag = 8; 60 61 // The magic string at the start of an archive. 62 static const char armag[sarmag]; 63 static const char armagt[sarmag]; 64 65 // The string expected at the end of an archive member header. 66 static const char arfmag[2]; 67 68 // The name of the object. This is the name used on the command 69 // line; e.g., if "-lgcc" is on the command line, this will be 70 // "gcc". 71 const std::string& 72 name() const 73 { return this->name_; } 74 75 // The file name. 76 const std::string& 77 filename() const 78 { return this->input_file_->filename(); } 79 80 // Set up the archive: read the symbol map. 81 void 82 setup(Input_objects*); 83 84 // Get a reference to the underlying file. 85 File_read& 86 file() 87 { return this->input_file_->file(); } 88 89 const File_read& 90 file() const 91 { return this->input_file_->file(); } 92 93 // Lock the underlying file. 94 void 95 lock(const Task* t) 96 { this->input_file_->file().lock(t); } 97 98 // Unlock the underlying file. 99 void 100 unlock(const Task* t) 101 { this->input_file_->file().unlock(t); } 102 103 // Return whether the underlying file is locked. 104 bool 105 is_locked() const 106 { return this->input_file_->file().is_locked(); } 107 108 // Return the token, so that the task can be queued. 109 Task_token* 110 token() 111 { return this->input_file_->file().token(); } 112 113 // Release the underlying file. 114 void 115 release() 116 { this->input_file_->file().release(); } 117 118 // Clear uncached views in the underlying file. 119 void 120 clear_uncached_views() 121 { this->input_file_->file().clear_uncached_views(); } 122 123 // Whether this is a thin archive. 124 bool 125 is_thin_archive() const 126 { return this->is_thin_archive_; } 127 128 // Unlock any nested archives. 129 void 130 unlock_nested_archives(); 131 132 // Select members from the archive as needed and add them to the 133 // link. 134 void 135 add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*); 136 137 // Dump statistical information to stderr. 138 static void 139 print_stats(); 140 141 // Return the number of members in the archive. 142 size_t 143 count_members(); 144 145 private: 146 Archive(const Archive&); 147 Archive& operator=(const Archive&); 148 149 struct Archive_header; 150 151 // Total number of archives seen. 152 static unsigned int total_archives; 153 // Total number of archive members seen. 154 static unsigned int total_members; 155 // Number of archive members loaded. 156 static unsigned int total_members_loaded; 157 158 // Get a view into the underlying file. 159 const unsigned char* 160 get_view(off_t start, section_size_type size, bool aligned, bool cache) 161 { return this->input_file_->file().get_view(0, start, size, aligned, cache); } 162 163 // Read the archive symbol map. 164 void 165 read_armap(off_t start, section_size_type size); 166 167 // Read an archive member header at OFF. CACHE is whether to cache 168 // the file view. Return the size of the member, and set *PNAME to 169 // the name. 170 off_t 171 read_header(off_t off, bool cache, std::string* pname, off_t* nested_off); 172 173 // Interpret an archive header HDR at OFF. Return the size of the 174 // member, and set *PNAME to the name. 175 off_t 176 interpret_header(const Archive_header* hdr, off_t off, std::string* pname, 177 off_t* nested_off) const; 178 179 // Get the file and offset for an archive member, which may be an 180 // external member of a thin archive. Set *INPUT_FILE to the 181 // file containing the actual member, *MEMOFF to the offset 182 // within that file (0 if not a nested archive), and *MEMBER_NAME 183 // to the name of the archive member. Return TRUE on success. 184 bool 185 get_file_and_offset(off_t off, Input_objects* input_objects, 186 Input_file** input_file, off_t* memoff, 187 std::string* member_name); 188 189 // Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to 190 // the name of the member. 191 Object* 192 get_elf_object_for_member(off_t off, Input_objects* input_objects); 193 194 // Read the symbols from all the archive members in the link. 195 void 196 read_all_symbols(Input_objects* input_objects); 197 198 // Read the symbols from an archive member in the link. OFF is the file 199 // offset of the member header. 200 void 201 read_symbols(Input_objects* input_objects, off_t off); 202 203 // Include all the archive members in the link. 204 void 205 include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*); 206 207 // Include an archive member in the link. 208 void 209 include_member(Symbol_table*, Layout*, Input_objects*, off_t off, 210 Mapfile*, Symbol*, const char* why); 211 212 // Iterate over archive members. 213 class const_iterator; 214 215 const_iterator 216 begin(); 217 218 const_iterator 219 end(); 220 221 friend class const_iterator; 222 223 // An entry in the archive map of symbols to object files. 224 struct Armap_entry 225 { 226 // The offset to the symbol name in armap_names_. 227 off_t name_offset; 228 // The file offset to the object in the archive. 229 off_t file_offset; 230 }; 231 232 // An entry in the archive map of offsets to members. 233 struct Archive_member 234 { 235 Archive_member() 236 : obj_(NULL), sd_(NULL) 237 { } 238 Archive_member(Object* obj, Read_symbols_data* sd) 239 : obj_(obj), sd_(sd) 240 { } 241 // The object file. 242 Object* obj_; 243 // The data to pass from read_symbols() to add_symbols(). 244 Read_symbols_data* sd_; 245 }; 246 247 // A simple hash code for off_t values. 248 class Seen_hash 249 { 250 public: 251 size_t operator()(off_t val) const 252 { return static_cast<size_t>(val); } 253 }; 254 255 // For keeping track of open nested archives in a thin archive file. 256 typedef Unordered_map<std::string, Archive*> Nested_archive_table; 257 258 // Name of object as printed to user. 259 std::string name_; 260 // For reading the file. 261 Input_file* input_file_; 262 // The archive map. 263 std::vector<Armap_entry> armap_; 264 // The names in the archive map. 265 std::string armap_names_; 266 // The extended name table. 267 std::string extended_names_; 268 // Track which symbols in the archive map are for elements which are 269 // defined or which have already been included in the link. 270 std::vector<bool> armap_checked_; 271 // Track which elements have been included by offset. 272 Unordered_set<off_t, Seen_hash> seen_offsets_; 273 // Table of objects whose symbols have been pre-read. 274 std::map<off_t, Archive_member> members_; 275 // True if this is a thin archive. 276 const bool is_thin_archive_; 277 // Table of nested archives, indexed by filename. 278 Nested_archive_table nested_archives_; 279 // The directory search path. 280 Dirsearch* dirpath_; 281 // The task reading this archive. 282 Task *task_; 283 // Number of members in this archive; 284 unsigned int num_members_; 285 }; 286 287 // This class is used to read an archive and pick out the desired 288 // elements and add them to the link. 289 290 class Add_archive_symbols : public Task 291 { 292 public: 293 Add_archive_symbols(Symbol_table* symtab, Layout* layout, 294 Input_objects* input_objects, Mapfile* mapfile, 295 Archive* archive, Input_group* input_group, 296 Task_token* this_blocker, 297 Task_token* next_blocker) 298 : symtab_(symtab), layout_(layout), input_objects_(input_objects), 299 mapfile_(mapfile), archive_(archive), input_group_(input_group), 300 this_blocker_(this_blocker), next_blocker_(next_blocker) 301 { } 302 303 ~Add_archive_symbols(); 304 305 // The standard Task methods. 306 307 Task_token* 308 is_runnable(); 309 310 void 311 locks(Task_locker*); 312 313 void 314 run(Workqueue*); 315 316 std::string 317 get_name() const 318 { 319 if (this->archive_ == NULL) 320 return "Add_archive_symbols"; 321 return "Add_archive_symbols " + this->archive_->file().filename(); 322 } 323 324 private: 325 Symbol_table* symtab_; 326 Layout* layout_; 327 Input_objects* input_objects_; 328 Mapfile* mapfile_; 329 Archive* archive_; 330 Input_group* input_group_; 331 Task_token* this_blocker_; 332 Task_token* next_blocker_; 333 }; 334 335 } // End namespace gold. 336 337 #endif // !defined(GOLD_ARCHIVE_H) 338