2020-12-13 15:06:25 +03:00
|
|
|
#include "mold.h"
|
|
|
|
|
|
|
|
struct ArHdr {
|
|
|
|
char ar_name[16];
|
|
|
|
char ar_date[12];
|
|
|
|
char ar_uid[6];
|
|
|
|
char ar_gid[6];
|
|
|
|
char ar_mode[8];
|
|
|
|
char ar_size[10];
|
|
|
|
char ar_fmag[2];
|
|
|
|
};
|
|
|
|
|
2020-12-22 14:10:04 +03:00
|
|
|
std::vector<MemoryMappedFile *> read_thin_archive_members(MemoryMappedFile *mb) {
|
2020-12-22 11:37:49 +03:00
|
|
|
u8 *data = mb->data() + 8;
|
|
|
|
std::vector<MemoryMappedFile *> vec;
|
2020-12-13 15:06:25 +03:00
|
|
|
std::string_view strtab;
|
2020-12-22 11:37:49 +03:00
|
|
|
std::string basedir = mb->name.substr(0, mb->name.find_last_of('/'));
|
2020-12-13 15:06:25 +03:00
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
while (data < mb->data() + mb->size()) {
|
2020-12-13 15:06:25 +03:00
|
|
|
ArHdr &hdr = *(ArHdr *)data;
|
|
|
|
u8 *body = data + sizeof(hdr);
|
|
|
|
u64 size = atol(hdr.ar_size);
|
|
|
|
|
|
|
|
if (!memcmp(hdr.ar_name, "// ", 3)) {
|
|
|
|
strtab = {(char *)body, size};
|
|
|
|
data = body + size;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!memcmp(hdr.ar_name, "/ ", 2)) {
|
|
|
|
data = body + size;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdr.ar_name[0] != '/')
|
2020-12-22 11:37:49 +03:00
|
|
|
error(mb->name + ": filename is not stored as a long filename");
|
2020-12-13 15:06:25 +03:00
|
|
|
|
|
|
|
const char *start = strtab.data() + atoi(hdr.ar_name + 1);
|
|
|
|
std::string name = {start, strstr(start, "/\n")};
|
2020-12-19 12:31:46 +03:00
|
|
|
|
2020-12-22 12:33:16 +03:00
|
|
|
vec.push_back(MemoryMappedFile::must_open(basedir + "/" + name));
|
2020-12-13 15:06:25 +03:00
|
|
|
data = body;
|
|
|
|
}
|
|
|
|
return vec;
|
|
|
|
}
|
|
|
|
|
2020-12-22 14:10:04 +03:00
|
|
|
std::vector<MemoryMappedFile *> read_fat_archive_members(MemoryMappedFile *mb) {
|
2020-12-22 11:37:49 +03:00
|
|
|
u8 *data = mb->data() + 8;
|
|
|
|
std::vector<MemoryMappedFile *> vec;
|
2020-12-13 15:06:25 +03:00
|
|
|
std::string_view strtab;
|
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
while (data < mb->data() + mb->size()) {
|
2020-12-13 15:06:25 +03:00
|
|
|
ArHdr &hdr = *(ArHdr *)data;
|
|
|
|
u8 *body = data + sizeof(hdr);
|
|
|
|
u64 size = atol(hdr.ar_size);
|
|
|
|
data = body + size;
|
|
|
|
|
|
|
|
if (!memcmp(hdr.ar_name, "// ", 3)) {
|
|
|
|
strtab = {(char *)body, size};
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!memcmp(hdr.ar_name, "/ ", 2) || !memcmp(hdr.ar_name, "__.SYMDEF/", 10))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
|
|
|
|
if (hdr.ar_name[0] == '/') {
|
|
|
|
const char *start = strtab.data() + atoi(hdr.ar_name + 1);
|
|
|
|
name = {start, strstr(start, "/\n")};
|
|
|
|
} else {
|
|
|
|
name = {hdr.ar_name, strchr(hdr.ar_name, '/')};
|
|
|
|
}
|
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
vec.push_back(mb->slice(name, body - mb->data(), size));
|
2020-12-13 15:06:25 +03:00
|
|
|
}
|
|
|
|
return vec;
|
|
|
|
}
|
2020-12-19 12:31:46 +03:00
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
std::vector<MemoryMappedFile *> read_archive_members(MemoryMappedFile *mb) {
|
|
|
|
if (mb->size() < 8)
|
|
|
|
error(mb->name + ": not an archive file");
|
|
|
|
if (memcmp(mb->data(), "!<arch>\n", 8) && memcmp(mb->data(), "!<thin>\n", 8))
|
|
|
|
error(mb->name + ": not an archive file");
|
2020-12-19 12:31:46 +03:00
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
bool is_thin = !memcmp(mb->data(), "!<thin>\n", 8);
|
2020-12-19 12:31:46 +03:00
|
|
|
if (is_thin)
|
|
|
|
return read_thin_archive_members(mb);
|
|
|
|
return read_fat_archive_members(mb);
|
|
|
|
}
|