Skip to content

Commit

Permalink
Removed unused options (thin, deterministic, symbol table) and always…
Browse files Browse the repository at this point in the history
… use settings that the Rust compiler needs
  • Loading branch information
dpaoliello committed Apr 8, 2024
1 parent 0bd52bf commit 4e05a36
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 83 deletions.
7 changes: 6 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# A writer for object file ar archives

This is based on commit [8ef3e895a](https://github.com/llvm/llvm-project/tree/3d3ef9d073e1e27ea57480b371b7f5a9f5642ed2) (15.0.0-rc3) of LLVM's archive writer.
This is a Rust port of LLVM's archive writer (`ArchiveWriter.cpp`):
* Based on commit [8ef3e895a](https://github.com/llvm/llvm-project/tree/3d3ef9d073e1e27ea57480b371b7f5a9f5642ed2) (15.0.0-rc3).
* With the following options removed:
* Deterministic: always enabled.
* Thin: always disabled.
* Symbol tables: always enabled.

## License

Expand Down
102 changes: 23 additions & 79 deletions src/archive_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ fn print_big_archive_member_header<W: Write>(
Ok(())
}

fn use_string_table(thin: bool, name: &str) -> bool {
thin || name.len() >= 16 || name.contains('/')
fn use_string_table(name: &str) -> bool {
name.len() >= 16 || name.contains('/')
}

fn is_64bit_kind(kind: ArchiveKind) -> bool {
Expand All @@ -156,7 +156,6 @@ fn print_member_header<'m, W: Write, T: Write + Seek>(
string_table: &mut T,
member_names: &mut HashMap<&'m str, u64>,
kind: ArchiveKind,
thin: bool,
m: &'m NewArchiveMember<'m>,
mtime: u64,
size: u64,
Expand All @@ -165,7 +164,7 @@ fn print_member_header<'m, W: Write, T: Write + Seek>(
return print_bsd_member_header(w, pos, &m.member_name, mtime, m.uid, m.gid, m.perms, size);
}

if !use_string_table(thin, &m.member_name) {
if !use_string_table(&m.member_name) {
return print_gnu_small_member_header(
w,
m.member_name.clone(),
Expand All @@ -179,17 +178,12 @@ fn print_member_header<'m, W: Write, T: Write + Seek>(

write!(w, "/")?;
let name_pos;
if thin {
if let Some(&pos) = member_names.get(&*m.member_name) {
name_pos = pos;
} else {
name_pos = string_table.stream_position()?;
member_names.insert(&m.member_name, name_pos);
write!(string_table, "{}/\n", m.member_name)?;
} else {
if let Some(&pos) = member_names.get(&*m.member_name) {
name_pos = pos;
} else {
name_pos = string_table.stream_position()?;
member_names.insert(&m.member_name, name_pos);
write!(string_table, "{}/\n", m.member_name)?;
}
}
write!(w, "{:<15}", name_pos)?;
print_rest_of_member_header(w, mtime, m.uid, m.gid, m.perms, size)
Expand Down Expand Up @@ -217,10 +211,7 @@ fn compute_string_table(names: &[u8]) -> MemberData<'_> {
}
}

fn now(deterministic: bool) -> u64 {
if !deterministic {
todo!("non deterministic mode is not yet supported"); // FIXME
}
const fn now() -> u64 {
0
}

Expand Down Expand Up @@ -293,7 +284,6 @@ fn compute_symbol_table_size_and_pad(
fn write_symbol_table_header<W: Write + Seek>(
w: &mut W,
kind: ArchiveKind,
deterministic: bool,
size: u64,
prev_member_offset: u64,
) -> io::Result<()> {
Expand All @@ -304,29 +294,18 @@ fn write_symbol_table_header<W: Write + Seek>(
"__.SYMDEF"
};
let pos = w.stream_position()?;
print_bsd_member_header(w, pos, name, now(deterministic), 0, 0, 0, size)
print_bsd_member_header(w, pos, name, now(), 0, 0, 0, size)
} else if is_aix_big_archive(kind) {
print_big_archive_member_header(
w,
"",
now(deterministic),
0,
0,
0,
size,
prev_member_offset,
0,
)
print_big_archive_member_header(w, "", now(), 0, 0, 0, size, prev_member_offset, 0)
} else {
let name = if is_64bit_kind(kind) { "/SYM64" } else { "" };
print_gnu_small_member_header(w, name.to_string(), now(deterministic), 0, 0, 0, size)
print_gnu_small_member_header(w, name.to_string(), now(), 0, 0, 0, size)
}
}

fn write_symbol_table<W: Write + Seek>(
w: &mut W,
kind: ArchiveKind,
deterministic: bool,
members: &[MemberData<'_>],
string_table: &[u8],
prev_member_offset: u64,
Expand All @@ -341,7 +320,7 @@ fn write_symbol_table<W: Write + Seek>(

let offset_size = if is_64bit_kind(kind) { 8 } else { 4 };
let (size, pad) = compute_symbol_table_size_and_pad(kind, num_syms, offset_size, string_table);
write_symbol_table_header(w, kind, deterministic, size, prev_member_offset)?;
write_symbol_table_header(w, kind, size, prev_member_offset)?;

let mut pos = if is_aix_big_archive(kind) {
u64::try_from(std::mem::size_of::<big_archive::FixLenHdr>()).unwrap()
Expand Down Expand Up @@ -426,9 +405,6 @@ fn compute_member_data<'a, S: Write + Seek>(
string_table: &mut S,
sym_names: &mut Cursor<Vec<u8>>,
kind: ArchiveKind,
thin: bool,
deterministic: bool,
need_symbols: bool,
new_members: &'a [NewArchiveMember<'a>],
) -> io::Result<Vec<MemberData<'a>>> {
const PADDING_DATA: &[u8; 8] = &[b'\n'; 8];
Expand Down Expand Up @@ -490,7 +466,7 @@ fn compute_member_data<'a, S: Write + Seek>(
// See also the functions that handle the lookup:
// in lldb: ObjectContainerBSDArchive::Archive::FindObject()
// in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
let unique_timestamps = deterministic && is_darwin(kind);
let unique_timestamps = is_darwin(kind);
let mut filename_count = HashMap::new();
if unique_timestamps {
for m in new_members {
Expand All @@ -507,7 +483,7 @@ fn compute_member_data<'a, S: Write + Seek>(
for m in new_members {
let mut header = Vec::new();

let data: &[u8] = if thin { &[][..] } else { (*m.buf).as_ref() };
let data: &[u8] = (*m.buf).as_ref();

// ld64 expects the members to be 8-byte aligned for 64-bit content and at
// least 4-byte aligned for 32-bit content. Opt for the larger encoding
Expand Down Expand Up @@ -562,18 +538,13 @@ fn compute_member_data<'a, S: Write + Seek>(
string_table,
&mut member_names,
kind,
thin,
m,
mtime,
size,
)?;
}

let symbols = if need_symbols {
write_symbols(data, m.get_symbols, sym_names, &mut has_object)?
} else {
vec![]
};
let symbols = write_symbols(data, m.get_symbols, sym_names, &mut has_object)?;

pos += u64::try_from(header.len() + data.len() + padding.len()).unwrap();
ret.push(MemberData {
Expand All @@ -597,28 +568,12 @@ fn compute_member_data<'a, S: Write + Seek>(
pub fn write_archive_to_stream<W: Write + Seek>(
w: &mut W,
new_members: &[NewArchiveMember<'_>],
write_symtab: bool,
mut kind: ArchiveKind,
deterministic: bool,
thin: bool,
) -> io::Result<()> {
assert!(
!thin || !is_bsd_like(kind),
"Only the gnu format has a thin mode"
);

let mut sym_names = Cursor::new(Vec::new());
let mut string_table = Cursor::new(Vec::new());

let mut data = compute_member_data(
&mut string_table,
&mut sym_names,
kind,
thin,
deterministic,
write_symtab,
new_members,
)?;
let mut data = compute_member_data(&mut string_table, &mut sym_names, kind, new_members)?;

let sym_names = sym_names.into_inner();

Expand Down Expand Up @@ -646,13 +601,13 @@ pub fn write_archive_to_stream<W: Write + Seek>(

// The symbol table is put at the end of the big archive file. The symbol
// table is at the start of the archive file for other archive formats.
if write_symtab && !is_aix_big_archive(kind) {
if !is_aix_big_archive(kind) {
// We assume 32-bit offsets to see if 32-bit symbols are possible or not.
let (symtab_size, _pad) = compute_symbol_table_size_and_pad(kind, num_syms, 4, &sym_names);
last_member_header_offset += {
// FIXME avoid allocating memory here
let mut tmp = Cursor::new(vec![]);
write_symbol_table_header(&mut tmp, kind, deterministic, symtab_size, 0).unwrap();
write_symbol_table_header(&mut tmp, kind, symtab_size, 0).unwrap();
u64::try_from(tmp.into_inner().len()).unwrap()
} + symtab_size;

Expand All @@ -678,18 +633,14 @@ pub fn write_archive_to_stream<W: Write + Seek>(
}
}

if thin {
write!(w, "!<thin>\n")?;
} else if is_aix_big_archive(kind) {
if is_aix_big_archive(kind) {
write!(w, "<bigaf>\n")?;
} else {
write!(w, "!<arch>\n")?;
}

if !is_aix_big_archive(kind) {
if write_symtab {
write_symbol_table(w, kind, deterministic, &data, &sym_names, 0)?;
}
write_symbol_table(w, kind, &data, &sym_names, 0)?;

for m in data {
w.write_all(&m.header)?;
Expand Down Expand Up @@ -723,7 +674,7 @@ pub fn write_archive_to_stream<W: Write + Seek>(
let member_table_size =
u64::try_from(20 + 20 * member_offsets.len() + member_table_name_str_tbl_size).unwrap();

let global_symbol_offset = if write_symtab && num_syms > 0 {
let global_symbol_offset = if num_syms > 0 {
last_member_end_offset
+ align_to(
u64::try_from(std::mem::size_of::<big_archive::BigArMemHdrType>()).unwrap()
Expand Down Expand Up @@ -817,15 +768,8 @@ pub fn write_archive_to_stream<W: Write + Seek>(
w.write_all(&[0])?;
}

if write_symtab && num_syms > 0 {
write_symbol_table(
w,
kind,
deterministic,
&data,
&sym_names,
last_member_end_offset,
)?;
if num_syms > 0 {
write_symbol_table(w, kind, &data, &sym_names, last_member_end_offset)?;
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions tests/round_trip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@ fn round_trip_and_diff(
ar_archive_writer::write_archive_to_stream(
&mut output_bytes,
&[input_member],
true,
archive_kind,
true,
false,
)
.unwrap();

Expand Down

0 comments on commit 4e05a36

Please sign in to comment.