diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..42b068b --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +reorder_imports = true +imports_granularity = "Module" +wrap_comments = true diff --git a/src/dwarf/divination.rs b/src/dwarf/divination.rs index c99d13a..55fb860 100644 --- a/src/dwarf/divination.rs +++ b/src/dwarf/divination.rs @@ -1,13 +1,15 @@ //! # divination //! -//! the practice of seeking knowledge of the future or the unknown by supernatural means. +//! the practice of seeking knowledge of the future or the unknown by +//! supernatural means. //! //! we ask supernatural means (the dynamic linker) for knowledge of the future //! (where we will find the dwarves) //! -//! first, we ask the dynamic linker to give us the `.eh_frame` for the current binary using -//! the GNU extension (`_dl_find_object`)[https://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker-Introspection.html]. -//! then, we parse that as beautiful DWARF call frame information, as god (or rather, the x86-64 psABI) intended. +//! first, we ask the dynamic linker to give us the `.eh_frame` for the current +//! binary using the GNU extension (`_dl_find_object`)[https://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker-Introspection.html]. +//! then, we parse that as beautiful DWARF call frame information, as god (or +//! rather, the x86-64 psABI) intended. #![allow(non_camel_case_types)] @@ -23,7 +25,8 @@ struct dl_find_object { dlfo_map_start: *const ffi::c_void, dlfo_map_end: *const ffi::c_void, dlf_link_map: *const ffi::c_void, - /// A pointer to the `PT_GNU_EH_FRAME` segment (the `.eh_frame_hdr` section). + /// A pointer to the `PT_GNU_EH_FRAME` segment (the `.eh_frame_hdr` + /// section). dlfo_eh_frame: *const ffi::c_void, } @@ -164,7 +167,9 @@ impl fmt::Debug for Encoding { #[derive(Debug, Clone, Copy)] #[repr(u8)] enum ValueFormat { - /// Unsigned value is encoded using the Little Endian Base 128 (LEB128) as defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, 1993). + /// Unsigned value is encoded using the Little Endian Base 128 (LEB128) as + /// defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, + /// 1993). DW_EH_PE_uleb128 = 0x01, /// A 2 bytes unsigned value. DW_EH_PE_udata2 = 0x02, @@ -172,7 +177,9 @@ enum ValueFormat { DW_EH_PE_udata4 = 0x03, /// An 8 bytes unsigned value. DW_EH_PE_udata8 = 0x04, - /// Signed value is encoded using the Little Endian Base 128 (LEB128) as defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, 1993). + /// Signed value is encoded using the Little Endian Base 128 (LEB128) as + /// defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, + /// 1993). DW_EH_PE_sleb128 = 0x09, /// A 2 bytes signed value. DW_EH_PE_sdata2 = 0x0A, diff --git a/src/dwarf/mod.rs b/src/dwarf/mod.rs index 2f59057..4e08aa3 100644 --- a/src/dwarf/mod.rs +++ b/src/dwarf/mod.rs @@ -1,7 +1,8 @@ -//! this implements the stuff necessary to get the uwutables for actual unwinding +//! this implements the stuff necessary to get the uwutables for actual +//! unwinding //! -//! for this we need a DWARF parser and a DWARF call frame information interpreter (yes, that shit is basically a programming -//! language). See https://dwarfstd.org/doc/DWARF5.pdf for more information if more information is desired. +//! for this we need a DWARF parser and a DWARF call frame information +//! interpreter (yes, that shit is basically a programming language). See https://dwarfstd.org/doc/DWARF5.pdf for more information if more information is desired. mod divination; mod parse; diff --git a/src/dwarf/parse.rs b/src/dwarf/parse.rs index d58be41..f9b016a 100644 --- a/src/dwarf/parse.rs +++ b/src/dwarf/parse.rs @@ -11,16 +11,17 @@ //! LN //! ``` //! -//! The first column is the address for every location that contains code in a program -//! (a relative offset in shared object files). The remaining columns contain unwinding rules -//! that are associated with the indicated location. +//! The first column is the address for every location that contains code in a +//! program (a relative offset in shared object files). The remaining columns +//! contain unwinding rules that are associated with the indicated location. //! //! The CFA column defines the rule which computes the Canonical Frame Address -//! value; it may be either a register and a signed offset that are added together, or a -//! DWARF expression that is evaluated. +//! value; it may be either a register and a signed offset that are added +//! together, or a DWARF expression that is evaluated. //! -//! The remaining columns describe register numbers that indicate whether a register has been saved -//! and the rule to find the value for the previous frame. +//! The remaining columns describe register numbers that indicate whether a +//! register has been saved and the rule to find the value for the previous +//! frame. #![allow(non_upper_case_globals)] #[cfg(test)] @@ -28,7 +29,8 @@ mod tests; use core::ffi::CStr; -use alloc::{format, string::String}; +use alloc::format; +use alloc::string::String; /// The dwarf is invalid. This is fatal and should never happen. #[derive(Debug)] @@ -41,25 +43,27 @@ pub struct Expr; #[derive(Debug)] enum RegisterRule { - /// A register that has this rule has no recoverable value in the previous frame. - /// (By convention, it is not preserved by a callee.) + /// A register that has this rule has no recoverable value in the previous + /// frame. (By convention, it is not preserved by a callee.) Undefined, /// This register has not been modified from the previous frame. - /// (By convention, it is preserved by the callee, but the callee has not modified it.) + /// (By convention, it is preserved by the callee, but the callee has not + /// modified it.) SameValue, - /// The previous value of this register is saved at the address CFA+N where CFA - /// is the current CFA value and N is a signed offset + /// The previous value of this register is saved at the address CFA+N where + /// CFA is the current CFA value and N is a signed offset Offset(isize), - /// The previous value of this register is the value CFA+N where CFA is the current CFA value - /// and N is a signed offset. + /// The previous value of this register is the value CFA+N where CFA is the + /// current CFA value and N is a signed offset. ValOffset(isize), - /// The previous value of this register is stored in another register numbered R. + /// The previous value of this register is stored in another register + /// numbered R. Register(u16), - /// The previous value of this register is located at the address produced by - /// executing the DWARF expression E (see Section 2.5 on page 26) + /// The previous value of this register is located at the address produced + /// by executing the DWARF expression E (see Section 2.5 on page 26) Expression(Expr), - /// The previous value of this register is the value produced by executing the DWARF - /// expression E (see Section 2.5 on page 26). + /// The previous value of this register is the value produced by executing + /// the DWARF expression E (see Section 2.5 on page 26). ValExpression(Expr), /// The rule is defined externally to this specification by the augmenter. Architectural, @@ -85,44 +89,48 @@ impl ILeb128 { /// Common Information Entry #[derive(Debug, PartialEq)] pub struct Cie<'a> { - /// A null-terminated UTF-8 string that identifies the augmentation to this CIE or - /// to the FDEs that use it. If a reader encounters an augmentation string that is - /// unexpected, then only the following fields can be read: + /// A null-terminated UTF-8 string that identifies the augmentation to this + /// CIE or to the FDEs that use it. If a reader encounters an + /// augmentation string that is unexpected, then only the following + /// fields can be read: /// - CIE: length, CIE_id, version, augmentation /// - FDE: length, CIE_pointer, initial_location, address_range /// /// If there is no augmentation, this value is a zero byte. /// - /// The augmentation string allows users to indicate that there is additional - /// target-specific information in the CIE or FDE which is needed to virtually unwind a - /// stack frame. For example, this might be information about dynamically allocated data - /// which needs to be freed on exit from the routine. + /// The augmentation string allows users to indicate that there is + /// additional target-specific information in the CIE or FDE which is + /// needed to virtually unwind a stack frame. For example, this might be + /// information about dynamically allocated data which needs to be freed + /// on exit from the routine. /// - /// Because the .debug_frame section is useful independently of any .debug_info - /// section, the augmentation string always uses UTF-8 encoding. + /// Because the .debug_frame section is useful independently of any + /// .debug_info section, the augmentation string always uses UTF-8 + /// encoding. pub augmentation: &'a str, - /// A constant that is factored out of all advance location instructions (see - /// Section 6.4.2.1 on page 177). The resulting value is + /// A constant that is factored out of all advance location instructions + /// (see Section 6.4.2.1 on page 177). The resulting value is /// (operand * code_alignment_factor). pub code_alignment_factor: u128, /// A constant that is factored out of certain offset instructions (see - /// Sections 6.4.2.2 on page 177 and 6.4.2.3 on page 179). The resulting value is - /// (operand * data_alignment_factor). + /// Sections 6.4.2.2 on page 177 and 6.4.2.3 on page 179). The resulting + /// value is (operand * data_alignment_factor). pub data_alignment_factor: i128, - /// An unsigned LEB128 constant that indicates which column in the rule table - /// represents the return address of the function. Note that this column might not - /// correspond to an actual machine register. + /// An unsigned LEB128 constant that indicates which column in the rule + /// table represents the return address of the function. Note that this + /// column might not correspond to an actual machine register. pub return_address_register: u128, - /// A block of data whose contents are defined by the contents of the Augmentation - /// String as described below. This field is only present if the Augmentation String - /// contains the character 'z'. The size of this data is given by the Augentation Length. + /// A block of data whose contents are defined by the contents of the + /// Augmentation String as described below. This field is only present + /// if the Augmentation String contains the character 'z'. The size of + /// this data is given by the Augentation Length. pub augmentation_data: Option<&'a [u8]>, - /// A sequence of rules that are interpreted to create the initial setting of each - /// column in the table. - /// The default rule for all columns before interpretation of the initial instructions - /// is the undefined rule. However, an ABI authoring body or a compilation - /// system authoring body may specify an alternate default value for any or all - /// columns. + /// A sequence of rules that are interpreted to create the initial setting + /// of each column in the table. + /// The default rule for all columns before interpretation of the initial + /// instructions is the undefined rule. However, an ABI authoring body + /// or a compilation system authoring body may specify an alternate + /// default value for any or all columns. pub initial_instructions: &'a [u8], } @@ -130,20 +138,22 @@ pub struct Cie<'a> { #[derive(Debug, PartialEq)] pub struct Fde<'a> { /// A constant that gives the number of bytes of the header and instruction - /// stream for this function, not including the length field itself (see Section 7.2.2 - /// on page 184). The size of the length field plus the value of length must be an - /// integral multiple of the address size. + /// stream for this function, not including the length field itself (see + /// Section 7.2.2 on page 184). The size of the length field plus the + /// value of length must be an integral multiple of the address size. pub length: usize, - /// A constant offset into the .debug_frame section that denotes the CIE that is - /// associated with this FDE. + /// A constant offset into the .debug_frame section that denotes the CIE + /// that is associated with this FDE. pub cie_pointer: Id, - /// The address of the first location associated with this table entry. If the - /// segment_selector_size field of this FDE’s CIE is non-zero, the initial - /// location is preceded by a segment selector of the given length. + /// The address of the first location associated with this table entry. If + /// the segment_selector_size field of this FDE’s CIE is non-zero, the + /// initial location is preceded by a segment selector of the given + /// length. pub initial_location: usize, /// The number of bytes of program instructions described by this entry. pub address_range: usize, - /// A sequence of table defining instructions that are described in Section 6.4.2. + /// A sequence of table defining instructions that are described in Section + /// 6.4.2. pub instructions: &'a [u8], } @@ -152,17 +162,20 @@ pub enum Instruction { //-------- 6.4.2.1 Row Creation Instructions // /// The DW_CFA_set_loc instruction takes a single operand that represents a - /// target address. The required action is to create a new table row using the - /// specified address as the location. All other values in the new row are initially - /// identical to the current row. The new location value is always greater than the - /// current one. If the segment_selector_size field of this FDE’s CIE is non-zero, - /// the initial location is preceded by a segment selector of the given length. + /// target address. The required action is to create a new table row using + /// the specified address as the location. All other values in the new + /// row are initially identical to the current row. The new location + /// value is always greater than the current one. If the + /// segment_selector_size field of this FDE’s CIE is non-zero, + /// the initial location is preceded by a segment selector of the given + /// length. SetLoc(usize), /// The DW_CFA_advance_loc instruction takes a single operand (encoded with - /// the opcode) that represents a constant delta. The required action is to create a - /// new table row with a location value that is computed by taking the current - /// entry’s location value and adding the value of delta * code_alignment_factor. - /// All other values in the new row are initially identical to the current row + /// the opcode) that represents a constant delta. The required action is to + /// create a new table row with a location value that is computed by + /// taking the current entry’s location value and adding the value of + /// delta * code_alignment_factor. All other values in the new row are + /// initially identical to the current row AdvanceLoc(u8), /// The DW_CFA_advance_loc1 instruction takes a single ubyte operand that /// represents a constant delta. This instruction is identical to @@ -181,67 +194,69 @@ pub enum Instruction { // /// The DW_CFA_def_cfa instruction takes two unsigned LEB128 operands /// representing a register number and a (non-factored) offset. The required - /// action is to define the current CFA rule to use the provided register and offset + /// action is to define the current CFA rule to use the provided register + /// and offset DefCfa { register_number: ULeb128, offset: ULeb128, }, /// The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned /// LEB128 value representing a register number and a signed LEB128 factored - /// offset. This instruction is identical to DW_CFA_def_cfa except that the second - /// operand is signed and factored. The resulting offset is factored_offset * - /// data_alignment_factor. + /// offset. This instruction is identical to DW_CFA_def_cfa except that the + /// second operand is signed and factored. The resulting offset is + /// factored_offset * data_alignment_factor. DefCfaSf { register_number: ULeb128, offset: ULeb128, }, /// The DW_CFA_def_cfa_register instruction takes a single unsigned LEB128 - /// operand representing a register number. The required action is to define the - /// current CFA rule to use the provided register (but to keep the old offset). This - /// operation is valid only if the current CFA rule is defined to use a register and - /// offset. + /// operand representing a register number. The required action is to define + /// the current CFA rule to use the provided register (but to keep the + /// old offset). This operation is valid only if the current CFA rule is + /// defined to use a register and offset. DefCfaRegister(ULeb128), /// The DW_CFA_def_cfa_offset instruction takes a single unsigned LEB128 - /// operand representing a (non-factored) offset. The required action is to define - /// the current CFA rule to use the provided offset (but to keep the old register). - /// This operation is valid only if the current CFA rule is defined to use a register - /// and offset. + /// operand representing a (non-factored) offset. The required action is to + /// define the current CFA rule to use the provided offset (but to keep + /// the old register). This operation is valid only if the current CFA + /// rule is defined to use a register and offset. DefCfaOffset(ULeb128), /// The DW_CFA_def_cfa_offset_sf instruction takes a signed LEB128 operand /// representing a factored offset. This instruction is identical to - /// DW_CFA_def_cfa_offset except that the operand is signed and factored. The - /// resulting offset is factored_offset * data_alignment_factor. This operation is - /// valid only if the current CFA rule is defined to use a register and offset. + /// DW_CFA_def_cfa_offset except that the operand is signed and factored. + /// The resulting offset is factored_offset * data_alignment_factor. + /// This operation is valid only if the current CFA rule is defined to + /// use a register and offset. DefCfaOffsetSf(ULeb128), /// The DW_CFA_def_cfa_expression instruction takes a single operand encoded /// as a DW_FORM_exprloc value representing a DWARF expression. The - /// required action is to establish that expression as the means by which the - /// current CFA is computed. + /// required action is to establish that expression as the means by which + /// the current CFA is computed. DefCfaExpression(Expr), // //-------- 6.4.2.3 Register Rule Instructions // /// The DW_CFA_undefined instruction takes a single unsigned LEB128 operand - /// that represents a register number. The required action is to set the rule for the - /// specified register to “undefined.” + /// that represents a register number. The required action is to set the + /// rule for the specified register to “undefined.” Undefined(ULeb128), /// The DW_CFA_same_value instruction takes a single unsigned LEB128 - /// operand that represents a register number. The required action is to set the - /// rule for the specified register to “same value.” + /// operand that represents a register number. The required action is to set + /// the rule for the specified register to “same value.” SameValue(ULeb128), /// The DW_CFA_offset instruction takes two operands: a register number /// (encoded with the opcode) and an unsigned LEB128 constant representing a - /// factored offset. The required action is to change the rule for the register - /// indicated by the register number to be an offset(N) rule where the value of N - /// is factored offset * data_alignment_factor. + /// factored offset. The required action is to change the rule for the + /// register indicated by the register number to be an offset(N) rule + /// where the value of N is factored offset * data_alignment_factor. Offset { register_number: usize, factored_offset: ULeb128, }, /// The DW_CFA_offset_extended instruction takes two unsigned LEB128 /// operands representing a register number and a factored offset. This - /// instruction is identical to DW_CFA_offset except for the encoding and size of - /// the register operand. + /// instruction is identical to DW_CFA_offset except for the encoding and + /// size of the register operand. OffsetExtended { register_number: ULeb128, factored_offset: ULeb128, @@ -249,81 +264,85 @@ pub enum Instruction { /// The DW_CFA_offset_extended_sf instruction takes two operands: an /// unsigned LEB128 value representing a register number and a signed LEB128 /// factored offset. This instruction is identical to DW_CFA_offset_extended - /// except that the second operand is signed and factored. The resulting offset is - /// factored_offset * data_alignment_factor. + /// except that the second operand is signed and factored. The resulting + /// offset is factored_offset * data_alignment_factor. OffsetExtendedSf { register_number: ULeb128, factored_offste: ULeb128, }, /// The DW_CFA_val_offset instruction takes two unsigned LEB128 operands - /// representing a register number and a factored offset. The required action is to - /// change the rule for the register indicated by the register number to be a - /// val_offset(N) rule where the value of N is factored_offset * - /// data_alignment_factor. + /// representing a register number and a factored offset. The required + /// action is to change the rule for the register indicated by the + /// register number to be a val_offset(N) rule where the value of N is + /// factored_offset * data_alignment_factor. ValOffset { register_number: ULeb128, factored_offste: ULeb128, }, /// The DW_CFA_val_offset_sf instruction takes two operands: an unsigned /// LEB128 value representing a register number and a signed LEB128 factored - /// offset. This instruction is identical to DW_CFA_val_offset except that the - /// second operand is signed and factored. The resulting offset is factored_offset * - /// data_alignment_factor. + /// offset. This instruction is identical to DW_CFA_val_offset except that + /// the second operand is signed and factored. The resulting offset is + /// factored_offset * data_alignment_factor. ValOffsetSf { register_number: ULeb128, factored_offste: ULeb128, }, /// The DW_CFA_register instruction takes two unsigned LEB128 operands - /// representing register numbers. The required action is to set the rule for the - /// first register to be register(R) where R is the second register. + /// representing register numbers. The required action is to set the rule + /// for the first register to be register(R) where R is the second + /// register. Register { target_register: ULeb128, from_register: ULeb128, }, /// The DW_CFA_expression instruction takes two operands: an unsigned /// LEB128 value representing a register number, and a DW_FORM_block value - /// representing a DWARF expression. The required action is to change the rule - /// for the register indicated by the register number to be an expression(E) rule - /// where E is the DWARF expression. That is, the DWARF expression computes - /// the address. The value of the CFA is pushed on the DWARF evaluation stack - /// prior to execution of the DWARF expression. - /// See Section 6.4.2 on page 176 regarding restrictions on the DWARF expression - /// operators that can be used. + /// representing a DWARF expression. The required action is to change the + /// rule for the register indicated by the register number to be an + /// expression(E) rule where E is the DWARF expression. That is, the + /// DWARF expression computes the address. The value of the CFA is + /// pushed on the DWARF evaluation stack prior to execution of the DWARF + /// expression. See Section 6.4.2 on page 176 regarding restrictions on + /// the DWARF expression operators that can be used. Expression { register: ULeb128, expr: Expr }, /// The DW_CFA_val_expression instruction takes two operands: an unsigned /// LEB128 value representing a register number, and a DW_FORM_block value - /// representing a DWARF expression. The required action is to change the rule - /// for the register indicated by the register number to be a val_expression(E) - /// rule where E is the DWARF expression. That is, the DWARF expression - /// computes the value of the given register. The value of the CFA is pushed on - /// the DWARF evaluation stack prior to execution of the DWARF expression. - /// See Section 6.4.2 on page 176 regarding restrictions on the DWARF expression - /// operators that can be used. + /// representing a DWARF expression. The required action is to change the + /// rule for the register indicated by the register number to be a + /// val_expression(E) rule where E is the DWARF expression. That is, the + /// DWARF expression computes the value of the given register. The value + /// of the CFA is pushed on the DWARF evaluation stack prior to + /// execution of the DWARF expression. See Section 6.4.2 on page 176 + /// regarding restrictions on the DWARF expression operators that can be + /// used. ValExpression { register: ULeb128, expr: Expr }, /// The DW_CFA_restore instruction takes a single operand (encoded with the - /// opcode) that represents a register number. The required action is to change - /// the rule for the indicated register to the rule assigned it by the - /// initial_instructions in the CIE. + /// opcode) that represents a register number. The required action is to + /// change the rule for the indicated register to the rule assigned it + /// by the initial_instructions in the CIE. Restore(usize), /// The DW_CFA_restore_extended instruction takes a single unsigned LEB128 - /// operand that represents a register number. This instruction is identical to - /// DW_CFA_restore except for the encoding and size of the register operand. + /// operand that represents a register number. This instruction is identical + /// to DW_CFA_restore except for the encoding and size of the register + /// operand. RestoreExtended(ULeb128), // //-------- 6.4.2.4 Row State Instructions // /// The DW_CFA_remember_state instruction takes no operands. The required - /// action is to push the set of rules for every register onto an implicit stack. + /// action is to push the set of rules for every register onto an implicit + /// stack. RememberState, /// The DW_CFA_restore_state instruction takes no operands. The required - /// action is to pop the set of rules off the implicit stack and place them in the - /// current row. + /// action is to pop the set of rules off the implicit stack and place them + /// in the current row. RestoreState, // //-------- 6.4.2.5 Padding Instruction // - /// The DW_CFA_nop instruction has no operands and no required actions. It is - /// used as padding to make a CIE or FDE an appropriate size. + /// The DW_CFA_nop instruction has no operands and no required actions. It + /// is used as padding to make a CIE or FDE an appropriate size. Nop, } @@ -474,29 +493,34 @@ fn parse_augmentation_data(string: &str, data: &[u8]) -> Result<()> { assert_eq!(codes.next(), Some(b'z')); trace!("aug data {:x?}", data.0); - let mut aug_data = AugmentationData {pointer_encoding: None}; + let mut aug_data = AugmentationData { + pointer_encoding: None, + }; for code in codes { match code { - // If present, it indicates the presence of one argument in the Augmentation Data of the CIE, - // and a corresponding argument in the Augmentation Data of the FDE. - // The argument in the Augmentation Data of the CIE is 1-byte and represents the pointer encoding - // used for the argument in the Augmentation Data of the FDE, which is the address of a language-specific - // data area (LSDA). The size of the LSDA pointer is specified by the pointer encoding used. + // If present, it indicates the presence of one argument in the Augmentation Data of the + // CIE, and a corresponding argument in the Augmentation Data of the FDE. + // The argument in the Augmentation Data of the CIE is 1-byte and represents the pointer + // encoding used for the argument in the Augmentation Data of the FDE, which + // is the address of a language-specific data area (LSDA). The size of the + // LSDA pointer is specified by the pointer encoding used. b'L' => { let encoding = read_u8(data)?; aug_data.lsda_pointer_encoding = Some(encoding); } - // If present, it indicates the presence of two arguments in the Augmentation Data of the CIE. - // The first argument is 1-byte and represents the pointer encoding used for the second argument, - // which is the address of a personality routine handler. The personality routine is used to handle - // language and vendor-specific tasks. The system unwind library interface accesses the language-specific - // exception handling semantics via the pointer to the personality routine. The personality routine does not - // have an ABI-specific name. The size of the personality routine pointer is specified by the pointer encoding used. - b'P' => { - - } - // If present, The Augmentation Data shall include a 1 byte argument that represents the pointer encoding for the address pointers used in the FDE. + // If present, it indicates the presence of two arguments in the Augmentation Data of + // the CIE. The first argument is 1-byte and represents the pointer encoding + // used for the second argument, which is the address of a personality + // routine handler. The personality routine is used to handle language and + // vendor-specific tasks. The system unwind library interface accesses the + // language-specific exception handling semantics via the pointer to the + // personality routine. The personality routine does not + // have an ABI-specific name. The size of the personality routine pointer is specified + // by the pointer encoding used. + b'P' => {} + // If present, The Augmentation Data shall include a 1 byte argument that represents the + // pointer encoding for the address pointers used in the FDE. b'R' => { let encoding = read_u8(data)?; aug_data.pointer_encoding = Some(encoding); @@ -512,9 +536,10 @@ pub(super) struct InstrIter { } impl InstrIter { - /// Create a new `InstrIter` that will parse DWARF call frame information from `data`. - /// # Safety - /// `data` must be a pointer to valid DWARF call frame information with a null terminator. + /// Create a new `InstrIter` that will parse DWARF call frame information + /// from `data`. # Safety + /// `data` must be a pointer to valid DWARF call frame information with a + /// null terminator. pub(super) unsafe fn new(data: *const u8) -> Self { // SAFETY: uses random ass pointer Self { data } @@ -523,10 +548,11 @@ impl InstrIter { fn advance(&mut self) -> Option { // SAFETY: First, we assume that `data` currently points at a valid location. // After we read from it, we increment it. This has implications. We must assume - // that the dwarf parsing code in this module never calls `advance` more than it has to. - // This means that really `advance` should be unsafe, but marking it as unsafe would only make - // the code in here harder to read and not provide practical safety improvements. - // We do eagerly move the data pointer outside the bounds of the allocation, but only one + // that the dwarf parsing code in this module never calls `advance` more than it + // has to. This means that really `advance` should be unsafe, but + // marking it as unsafe would only make the code in here harder to read + // and not provide practical safety improvements. We do eagerly move the + // data pointer outside the bounds of the allocation, but only one // past the end, which is fine. unsafe { let first = self.data.read(); diff --git a/src/lib.rs b/src/lib.rs index e7345c3..49249be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,8 @@ extern crate alloc; -use core::{ffi, sync::atomic::AtomicPtr}; +use core::ffi; +use core::sync::atomic::AtomicPtr; // Get the macros into our local prelude. #[macro_use] @@ -36,8 +37,8 @@ pub unsafe extern "C" fn _UnwindRaiseException( stdext::abort(); } -// This is normally provided by the language runtime through the unwind info block. -// We don't want to access that usually because Rust messes with it :(. +// This is normally provided by the language runtime through the unwind info +// block. We don't want to access that usually because Rust messes with it :(. static PERSONALITY_ROUTINE: AtomicPtr<()> = AtomicPtr::new(core::ptr::null_mut()); pub unsafe fn set_personality_routine(routine: uw::PersonalityRoutine) { diff --git a/src/stdext.rs b/src/stdext.rs index 0a8a090..4bd0579 100644 --- a/src/stdext.rs +++ b/src/stdext.rs @@ -50,7 +50,8 @@ pub(crate) fn with_last_os_error_str(f: impl FnOnce(&str) -> R) -> R { // SAFETY: Our buffer length is passed correctly let error = unsafe { libc::strerror_r(errno(), buf.as_mut_ptr().cast(), buf.len()) }; - // SAFETY: strerror_r writes the string to buf, even if it didnt write anything, we did zero init it. + // SAFETY: strerror_r writes the string to buf, even if it didnt write anything, + // we did zero init it. let cstr = if error != 0 { ffi::CStr::from_bytes_with_nul(b"\n").unwrap() } else { diff --git a/src/uw.rs b/src/uw.rs index b697e03..6b0e2fc 100644 --- a/src/uw.rs +++ b/src/uw.rs @@ -7,14 +7,17 @@ pub enum _Unwind_Reason_Code { /// Nested foreign exceptions, or re-throwing a foreign exception, result in /// undefined behavior. _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - /// The personality routine encountered an error during phase 1, other than the specific error codes defined. + /// The personality routine encountered an error during phase 1, other than + /// the specific error codes defined. _URC_FATAL_PHASE1_ERROR = 3, - /// The personality routine encountered an error during phase 2, for instance a stack corruption. + /// The personality routine encountered an error during phase 2, for + /// instance a stack corruption. _URC_FATAL_PHASE2_ERROR = 2, _URC_NORMAL_STOP = 4, - /// The unwinder encountered the end of the stack during phase 1, without finding a handler. - /// The unwind runtime will not have modified the stack. - /// The C++ runtime will normally call uncaught_exception() in this case + /// The unwinder encountered the end of the stack during phase 1, without + /// finding a handler. The unwind runtime will not have modified the + /// stack. The C++ runtime will normally call uncaught_exception() in + /// this case _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, @@ -32,8 +35,10 @@ pub struct _Unwind_Exception { pub type _Unwind_Exception_Cleanup_Fn = fn(reason: _Unwind_Reason_Code, exc: *const _Unwind_Exception); -/// The _Unwind_Context type is an opaque type used to refer to a system-specific data structure used by the system unwinder. -/// This context is created and destroyed by the system, and passed to the personality routine during unwinding +/// The _Unwind_Context type is an opaque type used to refer to a +/// system-specific data structure used by the system unwinder. This context is +/// created and destroyed by the system, and passed to the personality routine +/// during unwinding pub struct _Unwind_Context {} pub type PersonalityRoutine = fn( diff --git a/src/walk/mod.rs b/src/walk/mod.rs index 3cdd361..34a0be6 100644 --- a/src/walk/mod.rs +++ b/src/walk/mod.rs @@ -1 +1 @@ -pub mod fp; \ No newline at end of file +pub mod fp;