1
1
mirror of https://github.com/rui314/mold.git synced 2024-12-27 10:23:41 +03:00
mold/archive_file.cc

108 lines
3.0 KiB
C++
Raw Normal View History

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];
};
2021-03-29 14:29:57 +03:00
template <typename E>
std::vector<MemoryMappedFile<E> *>
read_thin_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb) {
2021-03-29 10:48:23 +03:00
u8 *data = mb->data(ctx) + 8;
2021-03-29 14:29:57 +03:00
std::vector<MemoryMappedFile<E> *> vec;
2020-12-13 15:06:25 +03:00
std::string_view strtab;
2021-03-29 10:48:23 +03:00
while (data < mb->data(ctx) + 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] != '/')
2021-03-29 10:48:23 +03:00
Fatal(ctx) << 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, (const char *)strstr(start, "/\n"));
std::string path = name.starts_with('/') ?
name : std::string(path_dirname(mb->name)) + "/" + name;
2021-03-29 14:29:57 +03:00
vec.push_back(MemoryMappedFile<E>::must_open(ctx, path));
2020-12-13 15:06:25 +03:00
data = body;
}
return vec;
}
2021-03-29 14:29:57 +03:00
template <typename E>
std::vector<MemoryMappedFile<E> *>
read_fat_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb) {
2021-03-29 10:48:23 +03:00
u8 *data = mb->data(ctx) + 8;
2021-03-29 14:29:57 +03:00
std::vector<MemoryMappedFile<E> *> vec;
2020-12-13 15:06:25 +03:00
std::string_view strtab;
2021-03-29 10:48:23 +03:00
while (mb->data(ctx) + mb->size() - data >= 2) {
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;
}
2021-03-12 07:17:45 +03:00
if (!memcmp(hdr.ar_name, "/ ", 2) ||
!memcmp(hdr.ar_name, "__.SYMDEF/", 10))
2020-12-13 15:06:25 +03:00
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")};
2020-12-13 15:06:25 +03:00
} else {
name = {hdr.ar_name, strchr(hdr.ar_name, '/')};
}
2021-04-07 09:38:31 +03:00
vec.push_back(mb->slice(ctx, name, body - mb->data(ctx), size));
2020-12-13 15:06:25 +03:00
}
return vec;
}
2021-03-29 14:29:57 +03:00
2021-06-14 06:53:16 +03:00
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);
}
}
2021-06-07 17:36:05 +03:00
#define INSTANTIATE(E) \
template std::vector<MemoryMappedFile<E> *> \
read_fat_archive_members(Context<E> &, MemoryMappedFile<E> *); \
template std::vector<MemoryMappedFile<E> *> \
2021-06-14 06:53:16 +03:00
read_thin_archive_members(Context<E> &, MemoryMappedFile<E> *); \
template std::vector<MemoryMappedFile<E> *> \
read_archive_members(Context<E> &, MemoryMappedFile<E> *);
2021-06-07 17:36:05 +03:00
INSTANTIATE(X86_64);
INSTANTIATE(I386);