mirror of
https://github.com/rui314/mold.git
synced 2024-12-26 18:02:30 +03:00
107 lines
3.0 KiB
C++
107 lines
3.0 KiB
C++
#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];
|
|
};
|
|
|
|
template <typename E>
|
|
std::vector<MemoryMappedFile<E> *>
|
|
read_thin_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb) {
|
|
u8 *data = mb->data(ctx) + 8;
|
|
std::vector<MemoryMappedFile<E> *> vec;
|
|
std::string_view strtab;
|
|
|
|
while (data < mb->data(ctx) + mb->size()) {
|
|
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] != '/')
|
|
Fatal(ctx) << mb->name << ": filename is not stored as a long filename";
|
|
|
|
const char *start = strtab.data() + atoi(hdr.ar_name + 1);
|
|
std::string name(start, (const char *)strstr(start, "/\n"));
|
|
std::string path = std::string(path_dirname(mb->name)) + "/" + name;
|
|
vec.push_back(MemoryMappedFile<E>::must_open(ctx, path));
|
|
data = body;
|
|
}
|
|
return vec;
|
|
}
|
|
|
|
template <typename E>
|
|
std::vector<MemoryMappedFile<E> *>
|
|
read_fat_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb) {
|
|
u8 *data = mb->data(ctx) + 8;
|
|
std::vector<MemoryMappedFile<E> *> vec;
|
|
std::string_view strtab;
|
|
|
|
while (mb->data(ctx) + mb->size() - data >= 2) {
|
|
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, (const char *)strstr(start, "/\n")};
|
|
} else {
|
|
name = {hdr.ar_name, strchr(hdr.ar_name, '/')};
|
|
}
|
|
|
|
vec.push_back(mb->slice(ctx, name, body - mb->data(ctx), size));
|
|
}
|
|
return vec;
|
|
}
|
|
|
|
template <typename E>
|
|
std::vector<MemoryMappedFile<E> *>
|
|
read_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb) {
|
|
switch (get_file_type(ctx, mb)) {
|
|
case FileType::AR:
|
|
return read_fat_archive_members(ctx, mb);
|
|
case FileType::THIN_AR:
|
|
return read_thin_archive_members(ctx, mb);
|
|
default:
|
|
unreachable(ctx);
|
|
}
|
|
}
|
|
|
|
#define INSTANTIATE(E) \
|
|
template std::vector<MemoryMappedFile<E> *> \
|
|
read_fat_archive_members(Context<E> &, MemoryMappedFile<E> *); \
|
|
template std::vector<MemoryMappedFile<E> *> \
|
|
read_thin_archive_members(Context<E> &, MemoryMappedFile<E> *); \
|
|
template std::vector<MemoryMappedFile<E> *> \
|
|
read_archive_members(Context<E> &, MemoryMappedFile<E> *);
|
|
|
|
INSTANTIATE(X86_64);
|
|
INSTANTIATE(I386);
|