mirror of
https://github.com/rui314/mold.git
synced 2024-09-11 13:06:59 +03:00
Move target-independent files to the top directory
This commit is contained in:
parent
8f10ac5047
commit
78bddacd5b
@ -17,7 +17,7 @@
|
||||
#include <tbb/parallel_for_each.h>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace mold::elf {
|
||||
namespace mold {
|
||||
|
||||
static constexpr i64 SHARD_SIZE = 1024 * 1024;
|
||||
|
||||
@ -41,7 +41,7 @@ static std::vector<u8> do_compress(std::string_view input) {
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
int r = deflateInit2(&strm, 3, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
|
||||
ASSERT(r == Z_OK);
|
||||
assert(r == Z_OK);
|
||||
|
||||
// Set an input buffer
|
||||
strm.avail_in = input.size();
|
||||
@ -55,8 +55,8 @@ static std::vector<u8> do_compress(std::string_view input) {
|
||||
strm.next_out = buf.data();
|
||||
|
||||
r = deflate(&strm, Z_SYNC_FLUSH);
|
||||
ASSERT(r == Z_OK);
|
||||
ASSERT(strm.avail_out > 0);
|
||||
assert(r == Z_OK);
|
||||
assert(strm.avail_out > 0);
|
||||
|
||||
buf.resize(buf.size() - strm.avail_out);
|
||||
deflateEnd(&strm);
|
||||
@ -163,4 +163,4 @@ void GzipCompressor::write_to(u8 *buf) {
|
||||
*(u32 *)(end - 4) = uncompressed_size;
|
||||
}
|
||||
|
||||
} // namespace mold::elf
|
||||
} // namespace mold
|
@ -1,83 +0,0 @@
|
||||
#include "mold.h"
|
||||
|
||||
namespace mold::elf {
|
||||
|
||||
static const char *locked = (char *)-1;
|
||||
|
||||
template <typename T>
|
||||
ConcurrentMap<T>::ConcurrentMap() {}
|
||||
|
||||
template <typename T>
|
||||
ConcurrentMap<T>::ConcurrentMap(i64 nbuckets) {
|
||||
resize(nbuckets);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ConcurrentMap<T>::resize(i64 nbuckets) {
|
||||
this->~ConcurrentMap();
|
||||
|
||||
nbuckets = std::max<i64>(MIN_NBUCKETS, next_power_of_two(nbuckets));
|
||||
|
||||
this->nbuckets = nbuckets;
|
||||
keys = (std::atomic<const char *> *)calloc(nbuckets, sizeof(keys[0]));
|
||||
sizes = (u32 *)calloc(nbuckets, sizeof(sizes[0]));
|
||||
values = (T *)calloc(nbuckets, sizeof(values[0]));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ConcurrentMap<T>::~ConcurrentMap() {
|
||||
if (keys) {
|
||||
free((void *)keys);
|
||||
free((void *)sizes);
|
||||
free((void *)values);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::pair<T *, bool>
|
||||
ConcurrentMap<T>::insert(std::string_view key, u64 hash, const T &val) {
|
||||
if (!keys)
|
||||
return {nullptr, false};
|
||||
|
||||
ASSERT(__builtin_popcount(nbuckets) == 1);
|
||||
i64 idx = hash & (nbuckets - 1);
|
||||
i64 retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
const char *ptr = keys[idx];
|
||||
if (ptr == locked) {
|
||||
#ifdef __x86_64__
|
||||
asm volatile("pause" ::: "memory");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ptr == nullptr) {
|
||||
if (!keys[idx].compare_exchange_weak(ptr, locked))
|
||||
continue;
|
||||
new (values + idx) T(val);
|
||||
sizes[idx] = key.size();
|
||||
keys[idx] = key.data();
|
||||
return {values + idx, true};
|
||||
}
|
||||
|
||||
if (key.size() == sizes[idx] && memcmp(ptr, key.data(), sizes[idx]) == 0)
|
||||
return {values + idx, false};
|
||||
|
||||
u64 mask = nbuckets / NUM_SHARDS - 1;
|
||||
idx = (idx & ~mask) | ((idx + 1) & mask);
|
||||
retry++;
|
||||
}
|
||||
|
||||
ASSERT(false && "ConcurrentMap is full");
|
||||
return {nullptr, false};
|
||||
}
|
||||
|
||||
#define INSTANTIATE(E) \
|
||||
template class ConcurrentMap<SectionFragment<E>>;
|
||||
|
||||
INSTANTIATE(X86_64);
|
||||
INSTANTIATE(I386);
|
||||
INSTANTIATE(AARCH64);
|
||||
|
||||
} // namespace mold::elf
|
202
elf/mold.h
202
elf/mold.h
@ -5,6 +5,7 @@
|
||||
#endif
|
||||
|
||||
#include "elf.h"
|
||||
#include "../mold.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
@ -44,16 +45,6 @@ template<> struct tbb::tbb_hash_compare<std::string_view> {
|
||||
|
||||
namespace mold::elf {
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
static constexpr i32 SECTOR_SIZE = 512;
|
||||
static constexpr i32 COMMON_PAGE_SIZE = 4096;
|
||||
static constexpr i32 SHA256_SIZE = 32;
|
||||
@ -77,12 +68,6 @@ template <typename E> class ROutputShdr;
|
||||
template <typename E> class RStrtabSection;
|
||||
template <typename E> class RSymtabSection;
|
||||
|
||||
template <typename T> class ConcurrentMap;
|
||||
|
||||
class ZlibCompressor;
|
||||
class GzipCompressor;
|
||||
class TarFile;
|
||||
|
||||
template <typename E> void cleanup();
|
||||
|
||||
template <typename E>
|
||||
@ -301,63 +286,6 @@ private:
|
||||
void report_undef(Context<E> &ctx, Symbol<E> &sym);
|
||||
};
|
||||
|
||||
//
|
||||
// hyperloglog.cc
|
||||
//
|
||||
|
||||
class HyperLogLog {
|
||||
public:
|
||||
HyperLogLog() : buckets(NBUCKETS) {}
|
||||
|
||||
void insert(u32 hash) {
|
||||
merge_one(hash & (NBUCKETS - 1), __builtin_clz(hash) + 1);
|
||||
}
|
||||
|
||||
void merge_one(i64 idx, u8 newval) {
|
||||
u8 cur = buckets[idx];
|
||||
while (cur < newval)
|
||||
if (buckets[idx].compare_exchange_strong(cur, newval))
|
||||
break;
|
||||
}
|
||||
|
||||
i64 get_cardinality() const;
|
||||
void merge(const HyperLogLog &other);
|
||||
|
||||
private:
|
||||
static constexpr i64 NBUCKETS = 2048;
|
||||
static constexpr double ALPHA = 0.79402;
|
||||
|
||||
std::vector<std::atomic_uint8_t> buckets;
|
||||
};
|
||||
|
||||
//
|
||||
// concurrent-map.cc
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
class ConcurrentMap {
|
||||
public:
|
||||
ConcurrentMap();
|
||||
ConcurrentMap(i64 nbuckets);
|
||||
~ConcurrentMap();
|
||||
|
||||
void resize(i64 nbuckets);
|
||||
std::pair<T *, bool> insert(std::string_view key, u64 hash, const T &val);
|
||||
|
||||
bool has_key(i64 idx) {
|
||||
return keys[idx];
|
||||
}
|
||||
|
||||
static constexpr i64 MIN_NBUCKETS = 2048;
|
||||
static constexpr i64 NUM_SHARDS = 16;
|
||||
static constexpr i64 MAX_RETRY = 128;
|
||||
|
||||
i64 nbuckets = 0;
|
||||
std::atomic<const char *> *keys = nullptr;
|
||||
u32 *sizes = nullptr;
|
||||
T *values = nullptr;
|
||||
};
|
||||
|
||||
//
|
||||
// output-chunks.cc
|
||||
//
|
||||
@ -1171,18 +1099,6 @@ protected:
|
||||
: path(path), filesize(filesize), is_mmapped(is_mmapped) {}
|
||||
};
|
||||
|
||||
//
|
||||
// filepath.cc
|
||||
//
|
||||
|
||||
// These are various utility functions to deal with file pathnames.
|
||||
std::string get_current_dir();
|
||||
std::string_view path_dirname(std::string_view path);
|
||||
std::string_view path_filename(std::string_view path);
|
||||
std::string_view path_basename(std::string_view path);
|
||||
std::string path_to_absolute(std::string_view path);
|
||||
std::string path_clean(std::string_view path);
|
||||
|
||||
//
|
||||
// perf.cc
|
||||
//
|
||||
@ -1318,59 +1234,6 @@ template <typename E>
|
||||
void parse_nonpositional_args(Context<E> &ctx,
|
||||
std::vector<std::string_view> &remaining);
|
||||
|
||||
//
|
||||
// compress.cc
|
||||
//
|
||||
|
||||
class ZlibCompressor {
|
||||
public:
|
||||
ZlibCompressor(std::string_view input);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const;
|
||||
|
||||
private:
|
||||
std::vector<std::vector<u8>> shards;
|
||||
u64 checksum = 0;
|
||||
};
|
||||
|
||||
class GzipCompressor {
|
||||
public:
|
||||
GzipCompressor(std::string_view input);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const;
|
||||
|
||||
private:
|
||||
std::vector<std::vector<u8>> shards;
|
||||
u32 checksum = 0;
|
||||
u32 uncompressed_size = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// tar.cc
|
||||
//
|
||||
|
||||
// TarFile is a class to create a tar file.
|
||||
//
|
||||
// If you pass `--reproduce=repro.tar` to mold, mold collects all
|
||||
// input files and put them into `repro.tar`, so that it is easy to
|
||||
// run the same command with the same command line arguments.
|
||||
class TarFile {
|
||||
public:
|
||||
static constexpr i64 BLOCK_SIZE = 512;
|
||||
|
||||
|
||||
TarFile(std::string basedir) : basedir(basedir) {}
|
||||
|
||||
void append(std::string path, std::string_view data);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const { return size_; }
|
||||
|
||||
private:
|
||||
std::string basedir;
|
||||
std::vector<std::pair<std::string, std::string_view>> contents;
|
||||
i64 size_ = BLOCK_SIZE * 2;
|
||||
};
|
||||
|
||||
//
|
||||
// passes.cc
|
||||
//
|
||||
@ -2123,21 +1986,6 @@ operator<<(std::ostream &out, const InputSection<E> &isec) {
|
||||
return out;
|
||||
}
|
||||
|
||||
inline u64 align_to(u64 val, u64 align) {
|
||||
if (align == 0)
|
||||
return val;
|
||||
ASSERT(__builtin_popcount(align) == 1);
|
||||
return (val + align - 1) & ~(align - 1);
|
||||
}
|
||||
|
||||
inline u64 next_power_of_two(u64 val) {
|
||||
ASSERT(val >> 63 == 0);
|
||||
if (val == 0 || val == 1)
|
||||
return 1;
|
||||
return (u64)1 << (64 - __builtin_clzl(val - 1));
|
||||
}
|
||||
|
||||
|
||||
template <typename E>
|
||||
inline u64 SectionFragment<E>::get_addr(Context<E> &ctx) const {
|
||||
return output_section.shdr.sh_addr + offset;
|
||||
@ -2306,52 +2154,4 @@ inline void write_vector(u8 *buf, const std::vector<T> &vec) {
|
||||
memcpy(buf, vec.data(), vec.size() * sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void append(std::vector<T> &vec1, std::vector<U> vec2) {
|
||||
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> flatten(std::vector<std::vector<T>> &vec) {
|
||||
std::vector<T> ret;
|
||||
for (std::vector<T> &v : vec)
|
||||
append(ret, v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void erase(std::vector<T> &vec, U pred) {
|
||||
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void sort(T &vec, U less) {
|
||||
std::stable_sort(vec.begin(), vec.end(), less);
|
||||
}
|
||||
|
||||
inline u64 read64be(u8 *buf) {
|
||||
return ((u64)buf[0] << 56) | ((u64)buf[1] << 48) |
|
||||
((u64)buf[2] << 40) | ((u64)buf[3] << 32) |
|
||||
((u64)buf[4] << 24) | ((u64)buf[5] << 16) |
|
||||
((u64)buf[6] << 8) | (u64)buf[7];
|
||||
}
|
||||
|
||||
inline void write64be(u8 *buf, u64 val) {
|
||||
buf[0] = val >> 56;
|
||||
buf[1] = val >> 48;
|
||||
buf[2] = val >> 40;
|
||||
buf[3] = val >> 32;
|
||||
buf[4] = val >> 24;
|
||||
buf[5] = val >> 16;
|
||||
buf[6] = val >> 8;
|
||||
buf[7] = val;
|
||||
}
|
||||
|
||||
inline void write32be(u8 *buf, u32 val) {
|
||||
buf[0] = val >> 24;
|
||||
buf[1] = val >> 16;
|
||||
buf[2] = val >> 8;
|
||||
buf[3] = val;
|
||||
}
|
||||
|
||||
} // namespace mold::elf
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "mold.h"
|
||||
|
||||
namespace mold::elf {
|
||||
namespace mold {
|
||||
|
||||
std::string get_current_dir() {
|
||||
std::string buf(8192, '\0');
|
||||
@ -106,4 +106,4 @@ std::string path_clean(std::string_view path) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace mold::elf
|
||||
} // namespace mold
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mold::elf {
|
||||
namespace mold {
|
||||
|
||||
i64 HyperLogLog::get_cardinality() const {
|
||||
double z = 0;
|
||||
@ -22,4 +22,4 @@ void HyperLogLog::merge(const HyperLogLog &other) {
|
||||
merge_one(i, other.buckets[i]);
|
||||
}
|
||||
|
||||
} // namespace mold::elf
|
||||
} // namespace mold
|
@ -1,3 +1,5 @@
|
||||
#include "../mold.h"
|
||||
|
||||
namespace mold::macho {
|
||||
|
||||
int macho_main(int argc, char **argv);
|
||||
|
2
main.cc
2
main.cc
@ -2,7 +2,7 @@
|
||||
#include "macho/mold.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::string_view cmd = mold::elf::path_filename(argv[0]);
|
||||
std::string_view cmd = mold::path_filename(argv[0]);
|
||||
|
||||
if (cmd == "ld" || cmd == "mold" || cmd == "ld.mold")
|
||||
return mold::elf::elf_main<mold::elf::X86_64>(argc, argv);
|
||||
|
275
mold.h
Normal file
275
mold.h
Normal file
@ -0,0 +1,275 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace mold {
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
//
|
||||
// Inline functions
|
||||
//
|
||||
|
||||
inline u64 align_to(u64 val, u64 align) {
|
||||
if (align == 0)
|
||||
return val;
|
||||
assert(__builtin_popcount(align) == 1);
|
||||
return (val + align - 1) & ~(align - 1);
|
||||
}
|
||||
|
||||
inline u64 next_power_of_two(u64 val) {
|
||||
assert(val >> 63 == 0);
|
||||
if (val == 0 || val == 1)
|
||||
return 1;
|
||||
return (u64)1 << (64 - __builtin_clzl(val - 1));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void append(std::vector<T> &vec1, std::vector<U> vec2) {
|
||||
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> flatten(std::vector<std::vector<T>> &vec) {
|
||||
std::vector<T> ret;
|
||||
for (std::vector<T> &v : vec)
|
||||
append(ret, v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void erase(std::vector<T> &vec, U pred) {
|
||||
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void sort(T &vec, U less) {
|
||||
std::stable_sort(vec.begin(), vec.end(), less);
|
||||
}
|
||||
|
||||
inline u64 read64be(u8 *buf) {
|
||||
return ((u64)buf[0] << 56) | ((u64)buf[1] << 48) |
|
||||
((u64)buf[2] << 40) | ((u64)buf[3] << 32) |
|
||||
((u64)buf[4] << 24) | ((u64)buf[5] << 16) |
|
||||
((u64)buf[6] << 8) | (u64)buf[7];
|
||||
}
|
||||
|
||||
inline void write64be(u8 *buf, u64 val) {
|
||||
buf[0] = val >> 56;
|
||||
buf[1] = val >> 48;
|
||||
buf[2] = val >> 40;
|
||||
buf[3] = val >> 32;
|
||||
buf[4] = val >> 24;
|
||||
buf[5] = val >> 16;
|
||||
buf[6] = val >> 8;
|
||||
buf[7] = val;
|
||||
}
|
||||
|
||||
inline void write32be(u8 *buf, u32 val) {
|
||||
buf[0] = val >> 24;
|
||||
buf[1] = val >> 16;
|
||||
buf[2] = val >> 8;
|
||||
buf[3] = val;
|
||||
}
|
||||
|
||||
//
|
||||
// Concurrent Map
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
class ConcurrentMap {
|
||||
public:
|
||||
ConcurrentMap() {}
|
||||
|
||||
ConcurrentMap(i64 nbuckets) {
|
||||
resize(nbuckets);
|
||||
}
|
||||
|
||||
~ConcurrentMap() {
|
||||
if (keys) {
|
||||
free((void *)keys);
|
||||
free((void *)sizes);
|
||||
free((void *)values);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(i64 nbuckets) {
|
||||
this->~ConcurrentMap();
|
||||
|
||||
nbuckets = std::max<i64>(MIN_NBUCKETS, next_power_of_two(nbuckets));
|
||||
|
||||
this->nbuckets = nbuckets;
|
||||
keys = (std::atomic<const char *> *)calloc(nbuckets, sizeof(keys[0]));
|
||||
sizes = (u32 *)calloc(nbuckets, sizeof(sizes[0]));
|
||||
values = (T *)calloc(nbuckets, sizeof(values[0]));
|
||||
}
|
||||
|
||||
std::pair<T *, bool> insert(std::string_view key, u64 hash, const T &val) {
|
||||
if (!keys)
|
||||
return {nullptr, false};
|
||||
|
||||
assert(__builtin_popcount(nbuckets) == 1);
|
||||
i64 idx = hash & (nbuckets - 1);
|
||||
i64 retry = 0;
|
||||
|
||||
while (retry < MAX_RETRY) {
|
||||
const char *ptr = keys[idx];
|
||||
if (ptr == locked) {
|
||||
#ifdef __x86_64__
|
||||
asm volatile("pause" ::: "memory");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ptr == nullptr) {
|
||||
if (!keys[idx].compare_exchange_weak(ptr, locked))
|
||||
continue;
|
||||
new (values + idx) T(val);
|
||||
sizes[idx] = key.size();
|
||||
keys[idx] = key.data();
|
||||
return {values + idx, true};
|
||||
}
|
||||
|
||||
if (key.size() == sizes[idx] && memcmp(ptr, key.data(), sizes[idx]) == 0)
|
||||
return {values + idx, false};
|
||||
|
||||
u64 mask = nbuckets / NUM_SHARDS - 1;
|
||||
idx = (idx & ~mask) | ((idx + 1) & mask);
|
||||
retry++;
|
||||
}
|
||||
|
||||
assert(false && "ConcurrentMap is full");
|
||||
return {nullptr, false};
|
||||
}
|
||||
|
||||
bool has_key(i64 idx) {
|
||||
return keys[idx];
|
||||
}
|
||||
|
||||
static constexpr i64 MIN_NBUCKETS = 2048;
|
||||
static constexpr i64 NUM_SHARDS = 16;
|
||||
static constexpr i64 MAX_RETRY = 128;
|
||||
|
||||
i64 nbuckets = 0;
|
||||
std::atomic<const char *> *keys = nullptr;
|
||||
u32 *sizes = nullptr;
|
||||
T *values = nullptr;
|
||||
|
||||
private:
|
||||
static constexpr const char *locked = "marker";
|
||||
};
|
||||
|
||||
//
|
||||
// hyperloglog.cc
|
||||
//
|
||||
|
||||
class HyperLogLog {
|
||||
public:
|
||||
HyperLogLog() : buckets(NBUCKETS) {}
|
||||
|
||||
void insert(u32 hash) {
|
||||
merge_one(hash & (NBUCKETS - 1), __builtin_clz(hash) + 1);
|
||||
}
|
||||
|
||||
void merge_one(i64 idx, u8 newval) {
|
||||
u8 cur = buckets[idx];
|
||||
while (cur < newval)
|
||||
if (buckets[idx].compare_exchange_strong(cur, newval))
|
||||
break;
|
||||
}
|
||||
|
||||
i64 get_cardinality() const;
|
||||
void merge(const HyperLogLog &other);
|
||||
|
||||
private:
|
||||
static constexpr i64 NBUCKETS = 2048;
|
||||
static constexpr double ALPHA = 0.79402;
|
||||
|
||||
std::vector<std::atomic_uint8_t> buckets;
|
||||
};
|
||||
|
||||
//
|
||||
// filepath.cc
|
||||
//
|
||||
|
||||
// These are various utility functions to deal with file pathnames.
|
||||
std::string get_current_dir();
|
||||
std::string_view path_dirname(std::string_view path);
|
||||
std::string_view path_filename(std::string_view path);
|
||||
std::string_view path_basename(std::string_view path);
|
||||
std::string path_to_absolute(std::string_view path);
|
||||
std::string path_clean(std::string_view path);
|
||||
|
||||
//
|
||||
// compress.cc
|
||||
//
|
||||
|
||||
class ZlibCompressor {
|
||||
public:
|
||||
ZlibCompressor(std::string_view input);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const;
|
||||
|
||||
private:
|
||||
std::vector<std::vector<u8>> shards;
|
||||
u64 checksum = 0;
|
||||
};
|
||||
|
||||
class GzipCompressor {
|
||||
public:
|
||||
GzipCompressor(std::string_view input);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const;
|
||||
|
||||
private:
|
||||
std::vector<std::vector<u8>> shards;
|
||||
u32 checksum = 0;
|
||||
u32 uncompressed_size = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// tar.cc
|
||||
//
|
||||
|
||||
// TarFile is a class to create a tar file.
|
||||
//
|
||||
// If you pass `--reproduce=repro.tar` to mold, mold collects all
|
||||
// input files and put them into `repro.tar`, so that it is easy to
|
||||
// run the same command with the same command line arguments.
|
||||
class TarFile {
|
||||
public:
|
||||
static constexpr i64 BLOCK_SIZE = 512;
|
||||
|
||||
|
||||
TarFile(std::string basedir) : basedir(basedir) {}
|
||||
|
||||
void append(std::string path, std::string_view data);
|
||||
void write_to(u8 *buf);
|
||||
i64 size() const { return size_; }
|
||||
|
||||
private:
|
||||
std::string basedir;
|
||||
std::vector<std::pair<std::string, std::string_view>> contents;
|
||||
i64 size_ = BLOCK_SIZE * 2;
|
||||
};
|
||||
|
||||
} // namespace mold
|
@ -1,6 +1,6 @@
|
||||
#include "mold.h"
|
||||
|
||||
namespace mold::elf {
|
||||
namespace mold {
|
||||
|
||||
// A tar file consists of one or more Ustar header followed by data.
|
||||
// Each Ustar header represents a single file in an archive.
|
||||
@ -67,7 +67,7 @@ void TarFile::write_to(u8 *buf) {
|
||||
memset(buf, 0, size_);
|
||||
|
||||
for (i64 i = 0; i < contents.size(); i++) {
|
||||
ASSERT(buf - start <= size_);
|
||||
assert(buf - start <= size_);
|
||||
|
||||
const std::string &path = contents[i].first;
|
||||
std::string_view data = contents[i].second;
|
||||
@ -99,4 +99,4 @@ void TarFile::write_to(u8 *buf) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mold::elf
|
||||
} // namespace mold
|
Loading…
Reference in New Issue
Block a user