From 2669953fa599b064582aaadc67d092e5144709dd Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Thu, 14 Oct 2021 18:35:58 -0700 Subject: [PATCH 1/6] Make the `write_core` and `write` features no_std compatible by no longer requiring the `std` feature. Note that the `write` feature could optionally enable `std`, if desired. Also, adjust the features required for example binaries. --- Cargo.toml | 7 ++++--- crates/examples/Cargo.toml | 6 +++--- src/lib.rs | 2 +- src/write/coff.rs | 4 ++-- src/write/elf/object.rs | 2 +- src/write/elf/writer.rs | 6 +++--- src/write/macho.rs | 2 +- src/write/mod.rs | 15 +++++++++------ src/write/pe.rs | 6 +++--- src/write/string.rs | 8 ++++++-- src/write/util.rs | 9 ++++++--- 11 files changed, 39 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 317dae3b..e87124f7 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,11 +13,12 @@ description = "A unified interface for reading and writing object file formats." features = ['doc'] [dependencies] -crc32fast = { version = "1.2", optional = true } +crc32fast = { version = "1.2", default-features = false, optional = true } flate2 = { version = "1", optional = true } indexmap = { version = "1.1", optional = true } wasmparser = { version = "0.57", optional = true } memchr = { version = "2.4.1", default-features = false } +hashbrown = { version = "0.9.1", features = ["ahash"], default-features = false, optional = true } # Internal feature, only used when building as part of libstd, not part of the # stable interface of this crate. @@ -34,7 +35,7 @@ read_core = [] # Read support for all file formats (including unaligned files). read = ["read_core", "archive", "coff", "elf", "macho", "pe", "unaligned"] # Core write support. You will need to enable some file formats too. -write_core = ["crc32fast", "indexmap/std", "std"] +write_core = ["crc32fast", "indexmap", "hashbrown"] # Write support for all file formats. write = ["write_core", "coff", "elf", "macho", "pe"] @@ -43,7 +44,7 @@ write = ["write_core", "coff", "elf", "macho", "pe"] # Enable things that require libstd. # Currently, this provides an `Error` implementation. -std = ["memchr/std"] +std = ["memchr/std", "indexmap/std", "crc32fast/std"] # Enable decompression of compressed sections. # This feature is not required if you want to do your own decompression. compression = ["flate2", "std"] diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml index 43197389..2cc82366 100644 --- a/crates/examples/Cargo.toml +++ b/crates/examples/Cargo.toml @@ -24,11 +24,11 @@ required-features = ["object/read"] [[bin]] name = "elfcopy" -required-features = ["object/read_core", "object/write_core", "object/elf"] +required-features = ["object/read_core", "object/write_core", "object/elf", "object/std"] [[bin]] name = "elftoefi" -required-features = ["object/read_core", "object/write_core", "object/elf", "object/pe"] +required-features = ["object/read_core", "object/write_core", "object/elf", "object/pe", "object/std"] [[bin]] name = "objcopy" @@ -48,7 +48,7 @@ required-features = ["object/read"] [[bin]] name = "pecopy" -required-features = ["object/read_core", "object/write_core", "object/pe"] +required-features = ["object/read_core", "object/write_core", "object/pe", "object/elf", "object/std"] [[bin]] name = "readobj" diff --git a/src/lib.rs b/src/lib.rs index 63c387d9..13eda90e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,7 +73,7 @@ #[cfg(feature = "cargo-all")] compile_error!("'--all-features' is not supported; use '--features all' instead"); -#[cfg(feature = "read_core")] +#[cfg(any(feature = "read_core", feature = "write_core"))] #[allow(unused_imports)] #[macro_use] extern crate alloc; diff --git a/src/write/coff.rs b/src/write/coff.rs index 5b6a27dc..486d667e 100644 --- a/src/write/coff.rs +++ b/src/write/coff.rs @@ -1,5 +1,5 @@ -use std::mem; -use std::vec::Vec; +use core::mem; +use alloc::vec::Vec; use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32}; use crate::pe as coff; diff --git a/src/write/elf/object.rs b/src/write/elf/object.rs index ffa09ffa..efcb8944 100644 --- a/src/write/elf/object.rs +++ b/src/write/elf/object.rs @@ -1,4 +1,4 @@ -use std::vec::Vec; +use alloc::vec::Vec; use crate::elf; use crate::write::elf::writer::*; diff --git a/src/write/elf/writer.rs b/src/write/elf/writer.rs index eb815856..80740a29 100644 --- a/src/write/elf/writer.rs +++ b/src/write/elf/writer.rs @@ -1,7 +1,7 @@ //! Helper for writing ELF files. -use std::mem; -use std::string::String; -use std::vec::Vec; +use alloc::string::String; +use alloc::vec::Vec; +use core::mem; use crate::elf; use crate::endian::*; diff --git a/src/write/macho.rs b/src/write/macho.rs index 1aec4428..db4a1dab 100644 --- a/src/write/macho.rs +++ b/src/write/macho.rs @@ -1,4 +1,4 @@ -use std::mem; +use core::mem; use crate::endian::*; use crate::macho; diff --git a/src/write/mod.rs b/src/write/mod.rs index 9113df08..21c1dc24 100644 --- a/src/write/mod.rs +++ b/src/write/mod.rs @@ -1,11 +1,12 @@ //! Interface for writing object files. -use std::borrow::Cow; -use std::boxed::Box; -use std::collections::HashMap; -use std::string::String; -use std::vec::Vec; -use std::{error, fmt, io, result, str}; +use alloc::borrow::Cow; +use hashbrown::HashMap; +use alloc::string::String; +use alloc::vec::Vec; +use core::{fmt, result, str}; +#[cfg(feature = "std")] +use std::{error, io, boxed::Box}; use crate::endian::{Endianness, U32, U64}; use crate::{ @@ -42,6 +43,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error {} /// The result type used within the write module. @@ -551,6 +553,7 @@ impl<'a> Object<'a> { /// /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter) /// instead of an unbuffered writer like [`File`](std::fs::File). + #[cfg(feature = "std")] pub fn write_stream(&self, w: W) -> result::Result<(), Box> { let mut stream = StreamingBuffer::new(w); self.emit(&mut stream)?; diff --git a/src/write/pe.rs b/src/write/pe.rs index 27d03097..bbd29a72 100644 --- a/src/write/pe.rs +++ b/src/write/pe.rs @@ -1,7 +1,7 @@ //! Helper for writing PE files. -use std::mem; -use std::string::String; -use std::vec::Vec; +use core::mem; +use alloc::string::String; +use alloc::vec::Vec; use crate::endian::{LittleEndian as LE, *}; use crate::pe; diff --git a/src/write/string.rs b/src/write/string.rs index e596fb27..3bdfccca 100644 --- a/src/write/string.rs +++ b/src/write/string.rs @@ -1,5 +1,9 @@ -use indexmap::IndexSet; -use std::vec::Vec; +use alloc::vec::Vec; + +#[cfg(feature = "std")] +type IndexSet = indexmap::IndexSet; +#[cfg(not(feature = "std"))] +type IndexSet = indexmap::IndexSet; /// An identifer for an entry in a string table. #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/write/util.rs b/src/write/util.rs index 02b96e47..51bc3515 100644 --- a/src/write/util.rs +++ b/src/write/util.rs @@ -1,6 +1,6 @@ -use std::io; -use std::mem; -use std::vec::Vec; +use alloc::vec::Vec; +#[cfg(feature = "std")] +use std::{io, mem}; use crate::pod::{bytes_of, bytes_of_slice, Pod}; @@ -86,6 +86,7 @@ impl WritableBuffer for Vec { /// /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter) /// instead of an unbuffered writer like [`File`](std::fs::File). +#[cfg(feature = "std")] #[derive(Debug)] pub struct StreamingBuffer { writer: W, @@ -93,6 +94,7 @@ pub struct StreamingBuffer { result: Result<(), io::Error>, } +#[cfg(feature = "std")] impl StreamingBuffer { /// Create a new `StreamingBuffer` backed by the given writer. pub fn new(writer: W) -> Self { @@ -114,6 +116,7 @@ impl StreamingBuffer { } } +#[cfg(feature = "std")] impl WritableBuffer for StreamingBuffer { #[inline] fn len(&self) -> usize { From 524cded80f9dcf686d5c31c36de21f0ae1ada121 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Fri, 19 Nov 2021 11:10:12 -0800 Subject: [PATCH 2/6] Match the hashbrown version used by the existing `indexmap` dependency. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e87124f7..0c03578f 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ flate2 = { version = "1", optional = true } indexmap = { version = "1.1", optional = true } wasmparser = { version = "0.57", optional = true } memchr = { version = "2.4.1", default-features = false } -hashbrown = { version = "0.9.1", features = ["ahash"], default-features = false, optional = true } +hashbrown = { version = "0.11", features = ["ahash"], default-features = false, optional = true } # Internal feature, only used when building as part of libstd, not part of the # stable interface of this crate. From 22c0fb0e380d4113497f96c0c671039d7b362bdd Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Fri, 19 Nov 2021 11:48:14 -0800 Subject: [PATCH 3/6] Remove the unnecessary `elf` feature from the `pecopy` example binary's required features. --- crates/examples/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml index 2cc82366..312d50fb 100644 --- a/crates/examples/Cargo.toml +++ b/crates/examples/Cargo.toml @@ -48,7 +48,7 @@ required-features = ["object/read"] [[bin]] name = "pecopy" -required-features = ["object/read_core", "object/write_core", "object/pe", "object/elf", "object/std"] +required-features = ["object/read_core", "object/write_core", "object/pe", "object/std"] [[bin]] name = "readobj" From 62f317fefd6e5ecf1c7b43f89f041596f0b7c79d Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Tue, 23 Nov 2021 11:54:40 -0800 Subject: [PATCH 4/6] * Separate the write-related std features into their own feature, `write_std`. * Remove optional features from the `std` feature that were enabled unconditionally even if `write_core` wasn't enabled. * Use the `hashbrown` `HashMap` implementation only if `std` is disabled, as before. --- Cargo.toml | 4 +++- src/write/mod.rs | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0c03578f..2032144c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,8 @@ read_core = [] read = ["read_core", "archive", "coff", "elf", "macho", "pe", "unaligned"] # Core write support. You will need to enable some file formats too. write_core = ["crc32fast", "indexmap", "hashbrown"] +# Core write support with libstd features. You will need to enable some file formats too. +write_std = ["write_core", "std", "indexmap/std", "crc32fast/std"] # Write support for all file formats. write = ["write_core", "coff", "elf", "macho", "pe"] @@ -44,7 +46,7 @@ write = ["write_core", "coff", "elf", "macho", "pe"] # Enable things that require libstd. # Currently, this provides an `Error` implementation. -std = ["memchr/std", "indexmap/std", "crc32fast/std"] +std = ["memchr/std"] # Enable decompression of compressed sections. # This feature is not required if you want to do your own decompression. compression = ["flate2", "std"] diff --git a/src/write/mod.rs b/src/write/mod.rs index 21c1dc24..154c926b 100644 --- a/src/write/mod.rs +++ b/src/write/mod.rs @@ -1,12 +1,13 @@ //! Interface for writing object files. use alloc::borrow::Cow; -use hashbrown::HashMap; use alloc::string::String; use alloc::vec::Vec; use core::{fmt, result, str}; #[cfg(feature = "std")] -use std::{error, io, boxed::Box}; +use std::{boxed::Box, collections::HashMap, error, io}; +#[cfg(not(feature = "std"))] +use hashbrown::HashMap; use crate::endian::{Endianness, U32, U64}; use crate::{ From 3a6965b5517d5dbd9c786455107e2dd15a339e50 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Tue, 23 Nov 2021 17:13:58 -0800 Subject: [PATCH 5/6] * Make the `write` feature enable `write_std` by default, which leaves the behavior of `write` unchanged from the perspective of dependent crates. * Add the `write_std` feature to the `doc` generation feature. This could optionally just be `write`, too. --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2032144c..c3cdf7c1 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,8 @@ read = ["read_core", "archive", "coff", "elf", "macho", "pe", "unaligned"] write_core = ["crc32fast", "indexmap", "hashbrown"] # Core write support with libstd features. You will need to enable some file formats too. write_std = ["write_core", "std", "indexmap/std", "crc32fast/std"] -# Write support for all file formats. -write = ["write_core", "coff", "elf", "macho", "pe"] +# Write support for all file formats, including libstd features. +write = ["write_std", "coff", "elf", "macho", "pe"] #======================================= # Misc features. @@ -82,7 +82,7 @@ cargo-all = [] #======================================= # Documentation should be generated with everything in "all" except for "unaligned". doc = [ - "read_core", "write_core", + "read_core", "write_std", "std", "compression", "archive", "coff", "elf", "macho", "pe", "wasm", ] From 97a86c5c7974a56afee7ff43da48fb0950b443f5 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Wed, 24 Nov 2021 10:28:07 -0800 Subject: [PATCH 6/6] Placate rustfmt --- src/write/coff.rs | 2 +- src/write/mod.rs | 4 ++-- src/write/pe.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/write/coff.rs b/src/write/coff.rs index 486d667e..23684efa 100644 --- a/src/write/coff.rs +++ b/src/write/coff.rs @@ -1,5 +1,5 @@ -use core::mem; use alloc::vec::Vec; +use core::mem; use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32}; use crate::pe as coff; diff --git a/src/write/mod.rs b/src/write/mod.rs index 154c926b..d7c5132b 100644 --- a/src/write/mod.rs +++ b/src/write/mod.rs @@ -4,10 +4,10 @@ use alloc::borrow::Cow; use alloc::string::String; use alloc::vec::Vec; use core::{fmt, result, str}; -#[cfg(feature = "std")] -use std::{boxed::Box, collections::HashMap, error, io}; #[cfg(not(feature = "std"))] use hashbrown::HashMap; +#[cfg(feature = "std")] +use std::{boxed::Box, collections::HashMap, error, io}; use crate::endian::{Endianness, U32, U64}; use crate::{ diff --git a/src/write/pe.rs b/src/write/pe.rs index bbd29a72..70da3a09 100644 --- a/src/write/pe.rs +++ b/src/write/pe.rs @@ -1,7 +1,7 @@ //! Helper for writing PE files. -use core::mem; use alloc::string::String; use alloc::vec::Vec; +use core::mem; use crate::endian::{LittleEndian as LE, *}; use crate::pe;