1
1
mirror of https://github.com/rui314/mold.git synced 2024-08-16 08:20:23 +03:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Jauder Ho
13b1779dd7
Merge 4011923433 into 18da5b654e 2024-07-09 05:47:42 +01:00
Rui Ueyama
18da5b654e Add --no-detach to write to a separate debug file in the foreground
--detach is the default.
2024-07-09 12:06:41 +09:00
Rui Ueyama
97a1e218c5 Simplify crc32_solve()
The code was originally written by Pete Cawley
https://gist.github.com/corsix/bdfc8f2f1dc0f28de39f74de9bf4f060
2024-07-09 10:15:26 +09:00
Jauder Ho
4011923433
Update dependabot.yml
Point to the right location for the Dockerfile
2023-07-28 10:11:52 -07:00
Jauder Ho
e391c4c2c2
Update dependabot.yml
Fix indentation
2023-07-28 10:06:40 -07:00
Jauder Ho
35208b2db6
Merge branch 'rui314:main' into patch-1 2023-07-28 10:05:41 -07:00
Jauder Ho
7606f36e26
Create dependabot.yml 2022-10-13 12:19:15 -07:00
6 changed files with 54 additions and 163 deletions

17
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,17 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/common" # Location of package manifests
schedule:
interval: "daily"

View File

@ -905,7 +905,7 @@ void release_global_lock();
//
u32 compute_crc32(u32 crc, u8 *buf, i64 len);
std::vector<u8> crc32_solve(i64 datalen, u32 current, u32 want);
std::vector<u8> crc32_solve(u32 current, u32 desired);
//
// compress.cc

View File

@ -1,42 +1,3 @@
// This file contains a function to "forge" a CRC. That is, given a piece
// of data and a desired CRC32 value, crc32_solve() returns a binary blob
// to add to the end of the original data to yield the desired CRC32
// value. A trailing garbage is ignored for many bianry file formats, so
// you can create a file with a desired CRC using crc32_solve(). We need
// it for --separate-debug-info.
//
// The code in this file is based on Mark Adler's "spoof" program. You can
// obtain the original copy of it at the following URL:
//
// https://github.com/madler/spoof/blob/master/spoof.c
//
// Below is the original license:
/* spoof.c -- modify a message to have a desired CRC
Copyright (C) 2012, 2014, 2016, 2018, 2021 Mark Adler
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler
madler@alumni.caltech.edu
*/
#include "common.h"
#include <tbb/parallel_for_each.h>
@ -44,101 +5,29 @@
namespace mold {
static constexpr i64 deg = 32;
static constexpr u32 poly = 0xedb88320;
// This function "forges" a CRC. That is, given the current and a desired
// CRC32 value, crc32_solve() returns a binary blob to add to the end of
// the original data to yield the desired CRC. Trailing garbage is ignored
// by many bianry file formats, so you can create a file with a desired
// CRC using crc32_solve(). We need it for --separate-debug-file.
std::vector<u8> crc32_solve(u32 current, u32 desired) {
constexpr u32 poly = 0xedb88320;
u32 x = ~desired;
using Mat = std::array<u32, deg>;
static constexpr u32 gf2_matrix_times(const Mat &mat, u32 vec) {
u32 n = 0;
for (i64 i = 0; vec; vec >>= 1, i++)
if (vec & 1)
n ^= mat[i];
return n;
}
static constexpr Mat gf2_matrix_square(const Mat &mat) {
Mat sq;
for (i64 i = 0; i < deg; i++)
sq[i] = gf2_matrix_times(mat, mat[i]);
return sq;
}
static consteval std::array<Mat, 64> get_crc_zero_powers() {
std::array<Mat, 64> p;
p[1][0] = poly;
for (i64 n = 1; n < deg; n++)
p[1][n] = 1 << (n - 1);
p[0] = gf2_matrix_square(p[1]);
p[1] = gf2_matrix_square(p[0]);
p[0] = gf2_matrix_square(p[1]);
p[1] = gf2_matrix_square(p[0]);
for (i64 i = 2; i < 64; i++)
p[i] = gf2_matrix_square(p[i - 1]);
return p;
}
// Efficiently apply len zero bytes to crc, returning the resulting crc.
static u32 crc_zeros(u32 crc, i64 len) {
static constexpr std::array<Mat, 64> power = get_crc_zero_powers();
// apply len zeros to crc
if (crc)
for (i64 n = 0; len; len >>= 1, n++)
if (len & 1)
crc = gf2_matrix_times(power[n], crc);
return crc;
}
// Solve M x = c for x
static std::vector<bool> gf2_matrix_solve(std::vector<u32> M, u32 c) {
i64 cols = M.size();
i64 rows = deg;
// create adjoining identity matrix
std::vector<std::vector<bool>> inv(cols);
for (i64 i = 0; i < cols; i++) {
inv[i].resize(cols);
inv[i][i] = 1;
// Each iteration computes x = (x * x^-1) mod poly.
for (i64 i = 0; i < 32; i++) {
x = std::rotl(x, 1);
x ^= (x & 1) * (poly << 1);
}
for (i64 j = 0; j < rows; j++) {
u32 pos = 1 << j;
x ^= ~current;
if ((M[j] & pos) == 0) {
i64 k;
for (k = j + 1; k < cols; k++)
if (M[k] & pos)
break;
if (k == cols) {
std::cerr << "mold: internal error: crc32_solve: no solution\n";
exit(1);
}
std::swap(M[j], M[k]);
std::swap(inv[j], inv[k]);
}
for (i64 k = 0; k < cols; k++) {
if (k != j && (M[k] & pos)) {
M[k] ^= M[j];
for (i64 i = 0; i < cols; i++)
inv[k][i] = inv[k][i] ^ inv[j][i];
}
}
}
// multiply inverse by c to get result x
std::vector<bool> x(cols);
for (i64 j = 0; c; c >>= 1, j++)
if (c & 1)
for (i64 i = 0; i < cols; i++)
x[i] = x[i] ^ inv[j][i];
return x;
std::vector<u8> out(4);
out[0] = x;
out[1] = x >> 8;
out[2] = x >> 16;
out[3] = x >> 24;
return out;
}
// Compute a CRC for given data in parallel
@ -168,30 +57,4 @@ u32 compute_crc32(u32 crc, u8 *buf, i64 len) {
return crc;
}
// Given input data and a desired CRC value, this function returns
// a binary blob such that if the blob is appended to the end of the
// input data, the entire data's CRC value becomes the desired CRC.
std::vector<u8> crc32_solve(i64 datalen, u32 current, u32 desired) {
// Compute the CRC for the given data and the all-zero trailer
constexpr i64 trailer_len = 16;
current = ~crc_zeros(~current, trailer_len);
// Compute CRCs for all bits in the trailer
std::vector<u32> mat;
for (i64 i = 0; i < trailer_len * 8; i++) {
u8 buf[trailer_len] = {};
buf[i / 8] = 1 << (i % 8);
mat.push_back(~crc32_z(~crc_zeros(0, datalen), buf, sizeof(buf)));
}
// Find desired trailer data
std::vector<bool> sol = gf2_matrix_solve(mat, desired ^ current);
std::vector<u8> out(trailer_len);
for (i64 i = 0; i < trailer_len * 8; i++)
if (sol[i])
out[i / 8] |= 1 << (i % 8);
return out;
}
} // namespace mold

View File

@ -85,6 +85,8 @@ Options:
--defsym=SYMBOL=VALUE Define a symbol alias
--demangle Demangle C++ symbols in log messages (default)
--no-demangle
--detach Create separate debug info file in the background (default)
--no-detach
--enable-new-dtags Emit DT_RUNPATH for --rpath (default)
--disable-new-dtags Emit DT_RPATH for --rpath
--execute-only Make executable segments unreadable
@ -759,6 +761,10 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
ctx.arg.demangle = true;
} else if (read_flag("no-demangle")) {
ctx.arg.demangle = false;
} else if (read_flag("detach")) {
ctx.arg.detach = true;
} else if (read_flag("no-detach")) {
ctx.arg.detach = false;
} else if (read_flag("default-symver")) {
ctx.arg.default_symver = true;
} else if (read_flag("noinhibit-exec")) {
@ -1413,6 +1419,10 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
if (ctx.arg.shared && warn_shared_textrel)
ctx.arg.warn_textrel = true;
// We don't want the background process to write to stdout
if (ctx.arg.stats || ctx.arg.perf)
ctx.arg.detach = false;
ctx.arg.undefined.push_back(ctx.arg.entry);
for (i64 i = 0; i < ctx.arg.defsyms.size(); i++) {

View File

@ -1740,6 +1740,7 @@ struct Context {
bool color_diagnostics = false;
bool default_symver = false;
bool demangle = true;
bool detach = true;
bool discard_all = false;
bool discard_locals = false;
bool eh_frame_hdr = true;

View File

@ -3058,7 +3058,7 @@ void write_separate_debug_file(Context<E> &ctx) {
// We want to write to the debug info file in background so that the
// user doesn't have to wait for it to complete.
if (!ctx.arg.stats && !ctx.arg.perf)
if (ctx.arg.detach)
notify_parent();
// A debug info file contains all sections as the original file, though
@ -3102,13 +3102,13 @@ void write_separate_debug_file(Context<E> &ctx) {
// Reverse-compute a CRC32 value so that the CRC32 checksum embedded to
// the .gnu_debuglink section in the main executable matches with the
// debug info file's CRC32 checksum.
std::vector<u8> &buf2 = ctx.output_file->buf2;
i64 datalen = filesize + buf2.size();
u32 crc = compute_crc32(0, ctx.buf, filesize);
crc = compute_crc32(crc, buf2.data(), buf2.size());
std::vector<u8> trailer = crc32_solve(datalen, crc, ctx.gnu_debuglink->crc32);
std::vector<u8> &buf2 = ctx.output_file->buf2;
if (!buf2.empty())
crc = compute_crc32(crc, buf2.data(), buf2.size());
std::vector<u8> trailer = crc32_solve(crc, ctx.gnu_debuglink->crc32);
append(ctx.output_file->buf2, trailer);
ctx.output_file->close(ctx);
}