Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

1
vendor/gimli/.cargo-checksum.json vendored Normal file
View File

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"8c5e124875aaba1b8ff61ab55e64164d866486874dd408cf90d9a22b659e0afe","Cargo.toml":"bf0b2be9dd65dbf7a867d52aa57affed9080d081e96cd9236a02d6294633359a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"847d6fe37773df4748bc20e9e810c6d378d3d9320a0a35f6a03feee630b99558","src/arch.rs":"7b5037bc1fa263c51b37bcab337e8a94ef82b6d4b70c0158e43a3c4154e61d58","src/common.rs":"301ec88e624ea0ab28a0b4c6819712feacc2886a3640b159f1a8b7eb007ac634","src/constants.rs":"cf37acb6703a3f7cbb5b26467721560a074a03f2a8dfd1a6104d916cb5255117","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"0dd6cff2e1fa56a79188b3b83c738b747af3288ef37f5e867e2a53971190818c","src/read/abbrev.rs":"4fc0efffe69e291dda890f0a66c12ae27053618119eefd7ec7303137364be18a","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"c1d7977921128721ecebafc56b86dac27a49664f9a0defb6dcfb50c4c4ff4dcf","src/read/dwarf.rs":"17c5daba222a268d48621fbacb451082fdc63891fc356e94fdc3c95616fe3b8b","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"c3e153a8a786498ee63a2d11b87371c7edb85d0e144242fe887c126250be80e3","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/line.rs":"19d38cbd27645885c59c41f7b8e7a509e0be1d701e4b30be13780744384c674b","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"857701a9e86aee809bfca3fd661e283b4f05038764dfc9c3cb1a349acc00bc47","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"35ba9167bbfbe38a82996fc343f79e22d6c83eba9daff6d048587ef6feb6baaa","src/read/op.rs":"2305f90e6cdf48ed7fbe67814d99d7a14662d030515b51aaad198807c13433e3","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"3e8ce504b651e14b839ef63c080c705ba7aef956ac2c7a74e298c015b791e2d2","src/read/rnglists.rs":"4ec166e73fdfc85efa97b3b005b514bb64d454edb1ba0f201c45df4f2127e745","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"60ecb8099d9386d85119b45ab92d628f3d3409b04669489b76e732d338b27f65","src/read/util.rs":"61e41212f1c8336988c9a7a1523c2913af8c8a66d2dd59d3631ba179e801e3bd","src/read/value.rs":"5ce8ef633f5af47bd367a5e4cde2c71bcef297c91a8d567192e460c890aef6de","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"e274b8b28f4e58c49ce530a5c630a26c6074be12f0faffed09709b700748afd7","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"73bf3bab57433fe1dc891c48303cbc4e482306a1b9425f3483ad2985a9676ee9","src/write/loc.rs":"5c1f8d97d8e871a6663ad704f5e15694bddd54b85f2d801b52a520522f1258fd","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"08fec7613aaa9061aae6e31d8b49933c812a6b7609f69e611a2a953af09aa18a","src/write/range.rs":"259e21e32bebbf7cdd8027d401862dee95cb5111e45bc4ff30bf54e3306d0262","src/write/section.rs":"effefef0d5e4557cb099431a20a7304392e6bf4ce04941d72b8bd2df9100e297","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"4a96a5f302b3bdf03faf3ff404bbcbed60d295080853ab8dabff5efa53f9ba37","src/write/writer.rs":"7d5dd07b82ec3becebb060c106d4ea697cbd8b9b64a5de78403511a5244e08b1"},"package":"4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"}

1022
vendor/gimli/CHANGELOG.md vendored Normal file

File diff suppressed because it is too large Load Diff

109
vendor/gimli/Cargo.toml vendored Normal file
View File

@ -0,0 +1,109 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.60"
name = "gimli"
version = "0.28.1"
include = [
"/CHANGELOG.md",
"/Cargo.toml",
"/LICENSE-APACHE",
"/LICENSE-MIT",
"/README.md",
"/src",
]
description = "A library for reading and writing the DWARF debugging format."
documentation = "https://docs.rs/gimli"
readme = "./README.md"
keywords = [
"DWARF",
"debug",
"ELF",
"eh_frame",
]
categories = [
"development-tools::debugging",
"development-tools::profiling",
"parser-implementations",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/gimli-rs/gimli"
resolver = "2"
[profile.bench]
codegen-units = 1
debug = 2
split-debuginfo = "packed"
[profile.test]
split-debuginfo = "packed"
[dependencies.alloc]
version = "1.0.0"
optional = true
package = "rustc-std-workspace-alloc"
[dependencies.compiler_builtins]
version = "0.1.2"
optional = true
[dependencies.core]
version = "1.0.0"
optional = true
package = "rustc-std-workspace-core"
[dependencies.fallible-iterator]
version = "0.3.0"
optional = true
default-features = false
[dependencies.indexmap]
version = "2.0.0"
optional = true
[dependencies.stable_deref_trait]
version = "1.1.0"
optional = true
default-features = false
[dev-dependencies.test-assembler]
version = "0.1.3"
[features]
default = [
"read-all",
"write",
]
endian-reader = [
"read",
"dep:stable_deref_trait",
]
fallible-iterator = ["dep:fallible-iterator"]
read = ["read-core"]
read-all = [
"read",
"std",
"fallible-iterator",
"endian-reader",
]
read-core = []
rustc-dep-of-std = [
"dep:core",
"dep:alloc",
"dep:compiler_builtins",
]
std = [
"fallible-iterator?/std",
"stable_deref_trait?/std",
]
write = ["dep:indexmap"]

201
vendor/gimli/LICENSE-APACHE vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
vendor/gimli/LICENSE-MIT vendored Normal file
View File

@ -0,0 +1,25 @@
Copyright (c) 2015 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

81
vendor/gimli/README.md vendored Normal file
View File

@ -0,0 +1,81 @@
# `gimli`
[![](https://img.shields.io/crates/v/gimli.svg) ![](https://img.shields.io/crates/d/gimli.svg)](https://crates.io/crates/gimli)
[![](https://docs.rs/gimli/badge.svg)](https://docs.rs/gimli/)
[![Build Status](https://github.com/gimli-rs/gimli/workflows/Rust/badge.svg)](https://github.com/gimli-rs/gimli/actions)
[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/gimli/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/gimli?branch=master)
`gimli` is a library for reading and writing the
[DWARF debugging format](https://dwarfstd.org/).
* **Zero copy:** everything is just a reference to the original input buffer. No
copies of the input data get made.
* **Lazy:** you can iterate compilation units without parsing their
contents. Parse only as many debugging information entry (DIE) trees as you
iterate over. `gimli` also uses `DW_AT_sibling` references to avoid parsing a
DIE's children to find its next sibling, when possible.
* **Cross-platform:** `gimli` makes no assumptions about what kind of object
file you're working with. The flipside to that is that it's up to you to
provide an ELF loader on Linux or Mach-O loader on macOS.
* Unsure which object file parser to use? Try the cross-platform
[`object`](https://github.com/gimli-rs/object) crate. See the
[`gimli-examples`](./crates/examples/src/bin) crate for usage with `gimli`.
## Install
Add this to your `Cargo.toml`:
```toml
[dependencies]
gimli = "0.28.1"
```
The minimum supported Rust version is:
* 1.60.0 for the `read` feature and its dependencies.
* 1.65.0 for other features.
## Documentation
* [Documentation on docs.rs](https://docs.rs/gimli/)
* Example programs:
* [A simple `.debug_info` parser](./crates/examples/src/bin/simple.rs)
* [A simple `.debug_line` parser](./crates/examples/src/bin/simple_line.rs)
* [A `dwarfdump` clone](./crates/examples/src/bin/dwarfdump.rs)
* [An `addr2line` clone](https://github.com/gimli-rs/addr2line)
* [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into
code generation by making debugging information readable.
* [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the
compilers used to create each compilation unit within a shared library or
executable (via `DW_AT_producer`).
* [`dwarf-validate`](./crates/examples/src/bin/dwarf-validate.rs), a program to validate the
integrity of some DWARF and its references between sections and compilation
units.
## License
Licensed under either of
* Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT)
at your option.
## Contribution
See [CONTRIBUTING.md](./CONTRIBUTING.md) for hacking.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

839
vendor/gimli/src/arch.rs vendored Normal file
View File

@ -0,0 +1,839 @@
use crate::common::Register;
macro_rules! registers {
($struct_name:ident, { $($name:ident = ($val:expr, $disp:expr)),+ $(,)? }
$(, aliases { $($alias_name:ident = ($alias_val:expr, $alias_disp:expr)),+ $(,)? })?) => {
#[allow(missing_docs)]
impl $struct_name {
$(
pub const $name: Register = Register($val);
)+
$(
$(pub const $alias_name: Register = Register($alias_val);)+
)*
}
impl $struct_name {
/// The name of a register, or `None` if the register number is unknown.
///
/// Only returns the primary name for registers that alias with others.
pub fn register_name(register: Register) -> Option<&'static str> {
match register {
$(
Self::$name => Some($disp),
)+
_ => return None,
}
}
/// Converts a register name into a register number.
pub fn name_to_register(value: &str) -> Option<Register> {
match value {
$(
$disp => Some(Self::$name),
)+
$(
$($alias_disp => Some(Self::$alias_name),)+
)*
_ => return None,
}
}
}
};
}
/// ARM architecture specific definitions.
///
/// See [DWARF for the ARM Architecture](
/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf32/aadwarf32.rst).
#[derive(Debug, Clone, Copy)]
pub struct Arm;
registers!(Arm, {
R0 = (0, "R0"),
R1 = (1, "R1"),
R2 = (2, "R2"),
R3 = (3, "R3"),
R4 = (4, "R4"),
R5 = (5, "R5"),
R6 = (6, "R6"),
R7 = (7, "R7"),
R8 = (8, "R8"),
R9 = (9, "R9"),
R10 = (10, "R10"),
R11 = (11, "R11"),
R12 = (12, "R12"),
R13 = (13, "R13"),
R14 = (14, "R14"),
R15 = (15, "R15"),
WCGR0 = (104, "wCGR0"),
WCGR1 = (105, "wCGR1"),
WCGR2 = (106, "wCGR2"),
WCGR3 = (107, "wCGR3"),
WCGR4 = (108, "wCGR4"),
WCGR5 = (109, "wCGR5"),
WCGR6 = (110, "wCGR6"),
WCGR7 = (111, "wCGR7"),
WR0 = (112, "wR0"),
WR1 = (113, "wR1"),
WR2 = (114, "wR2"),
WR3 = (115, "wR3"),
WR4 = (116, "wR4"),
WR5 = (117, "wR5"),
WR6 = (118, "wR6"),
WR7 = (119, "wR7"),
WR8 = (120, "wR8"),
WR9 = (121, "wR9"),
WR10 = (122, "wR10"),
WR11 = (123, "wR11"),
WR12 = (124, "wR12"),
WR13 = (125, "wR13"),
WR14 = (126, "wR14"),
WR15 = (127, "wR15"),
SPSR = (128, "SPSR"),
SPSR_FIQ = (129, "SPSR_FIQ"),
SPSR_IRQ = (130, "SPSR_IRQ"),
SPSR_ABT = (131, "SPSR_ABT"),
SPSR_UND = (132, "SPSR_UND"),
SPSR_SVC = (133, "SPSR_SVC"),
RA_AUTH_CODE = (143, "RA_AUTH_CODE"),
R8_USR = (144, "R8_USR"),
R9_USR = (145, "R9_USR"),
R10_USR = (146, "R10_USR"),
R11_USR = (147, "R11_USR"),
R12_USR = (148, "R12_USR"),
R13_USR = (149, "R13_USR"),
R14_USR = (150, "R14_USR"),
R8_FIQ = (151, "R8_FIQ"),
R9_FIQ = (152, "R9_FIQ"),
R10_FIQ = (153, "R10_FIQ"),
R11_FIQ = (154, "R11_FIQ"),
R12_FIQ = (155, "R12_FIQ"),
R13_FIQ = (156, "R13_FIQ"),
R14_FIQ = (157, "R14_FIQ"),
R13_IRQ = (158, "R13_IRQ"),
R14_IRQ = (159, "R14_IRQ"),
R13_ABT = (160, "R13_ABT"),
R14_ABT = (161, "R14_ABT"),
R13_UND = (162, "R13_UND"),
R14_UND = (163, "R14_UND"),
R13_SVC = (164, "R13_SVC"),
R14_SVC = (165, "R14_SVC"),
WC0 = (192, "wC0"),
WC1 = (193, "wC1"),
WC2 = (194, "wC2"),
WC3 = (195, "wC3"),
WC4 = (196, "wC4"),
WC5 = (197, "wC5"),
WC6 = (198, "wC6"),
WC7 = (199, "wC7"),
D0 = (256, "D0"),
D1 = (257, "D1"),
D2 = (258, "D2"),
D3 = (259, "D3"),
D4 = (260, "D4"),
D5 = (261, "D5"),
D6 = (262, "D6"),
D7 = (263, "D7"),
D8 = (264, "D8"),
D9 = (265, "D9"),
D10 = (266, "D10"),
D11 = (267, "D11"),
D12 = (268, "D12"),
D13 = (269, "D13"),
D14 = (270, "D14"),
D15 = (271, "D15"),
D16 = (272, "D16"),
D17 = (273, "D17"),
D18 = (274, "D18"),
D19 = (275, "D19"),
D20 = (276, "D20"),
D21 = (277, "D21"),
D22 = (278, "D22"),
D23 = (279, "D23"),
D24 = (280, "D24"),
D25 = (281, "D25"),
D26 = (282, "D26"),
D27 = (283, "D27"),
D28 = (284, "D28"),
D29 = (285, "D29"),
D30 = (286, "D30"),
D31 = (287, "D31"),
TPIDRURO = (320, "TPIDRURO"),
TPIDRURW = (321, "TPIDRURW"),
TPIDPR = (322, "TPIDPR"),
HTPIDPR = (323, "HTPIDPR"),
},
aliases {
SP = (13, "SP"),
LR = (14, "LR"),
PC = (15, "PC"),
ACC0 = (104, "ACC0"),
ACC1 = (105, "ACC1"),
ACC2 = (106, "ACC2"),
ACC3 = (107, "ACC3"),
ACC4 = (108, "ACC4"),
ACC5 = (109, "ACC5"),
ACC6 = (110, "ACC6"),
ACC7 = (111, "ACC7"),
S0 = (256, "S0"),
S1 = (256, "S1"),
S2 = (257, "S2"),
S3 = (257, "S3"),
S4 = (258, "S4"),
S5 = (258, "S5"),
S6 = (259, "S6"),
S7 = (259, "S7"),
S8 = (260, "S8"),
S9 = (260, "S9"),
S10 = (261, "S10"),
S11 = (261, "S11"),
S12 = (262, "S12"),
S13 = (262, "S13"),
S14 = (263, "S14"),
S15 = (263, "S15"),
S16 = (264, "S16"),
S17 = (264, "S17"),
S18 = (265, "S18"),
S19 = (265, "S19"),
S20 = (266, "S20"),
S21 = (266, "S21"),
S22 = (267, "S22"),
S23 = (267, "S23"),
S24 = (268, "S24"),
S25 = (268, "S25"),
S26 = (269, "S26"),
S27 = (269, "S27"),
S28 = (270, "S28"),
S29 = (270, "S29"),
S30 = (271, "S30"),
S31 = (271, "S31"),
});
/// ARM 64-bit (AArch64) architecture specific definitions.
///
/// See [DWARF for the ARM 64-bit Architecture](
/// https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst).
#[derive(Debug, Clone, Copy)]
pub struct AArch64;
registers!(AArch64, {
X0 = (0, "X0"),
X1 = (1, "X1"),
X2 = (2, "X2"),
X3 = (3, "X3"),
X4 = (4, "X4"),
X5 = (5, "X5"),
X6 = (6, "X6"),
X7 = (7, "X7"),
X8 = (8, "X8"),
X9 = (9, "X9"),
X10 = (10, "X10"),
X11 = (11, "X11"),
X12 = (12, "X12"),
X13 = (13, "X13"),
X14 = (14, "X14"),
X15 = (15, "X15"),
X16 = (16, "X16"),
X17 = (17, "X17"),
X18 = (18, "X18"),
X19 = (19, "X19"),
X20 = (20, "X20"),
X21 = (21, "X21"),
X22 = (22, "X22"),
X23 = (23, "X23"),
X24 = (24, "X24"),
X25 = (25, "X25"),
X26 = (26, "X26"),
X27 = (27, "X27"),
X28 = (28, "X28"),
X29 = (29, "X29"),
X30 = (30, "X30"),
SP = (31, "SP"),
PC = (32, "PC"),
ELR_MODE = (33, "ELR_mode"),
RA_SIGN_STATE = (34, "RA_SIGN_STATE"),
TPIDRRO_EL0 = (35, "TPIDRRO_EL0"),
TPIDR_EL0 = (36, "TPIDR_EL0"),
TPIDR_EL1 = (37, "TPIDR_EL1"),
TPIDR_EL2 = (38, "TPIDR_EL2"),
TPIDR_EL3 = (39, "TPIDR_EL3"),
VG = (46, "VG"),
FFR = (47, "FFR"),
P0 = (48, "P0"),
P1 = (49, "P1"),
P2 = (50, "P2"),
P3 = (51, "P3"),
P4 = (52, "P4"),
P5 = (53, "P5"),
P6 = (54, "P6"),
P7 = (55, "P7"),
P8 = (56, "P8"),
P9 = (57, "P9"),
P10 = (58, "P10"),
P11 = (59, "P11"),
P12 = (60, "P12"),
P13 = (61, "P13"),
P14 = (62, "P14"),
P15 = (63, "P15"),
V0 = (64, "V0"),
V1 = (65, "V1"),
V2 = (66, "V2"),
V3 = (67, "V3"),
V4 = (68, "V4"),
V5 = (69, "V5"),
V6 = (70, "V6"),
V7 = (71, "V7"),
V8 = (72, "V8"),
V9 = (73, "V9"),
V10 = (74, "V10"),
V11 = (75, "V11"),
V12 = (76, "V12"),
V13 = (77, "V13"),
V14 = (78, "V14"),
V15 = (79, "V15"),
V16 = (80, "V16"),
V17 = (81, "V17"),
V18 = (82, "V18"),
V19 = (83, "V19"),
V20 = (84, "V20"),
V21 = (85, "V21"),
V22 = (86, "V22"),
V23 = (87, "V23"),
V24 = (88, "V24"),
V25 = (89, "V25"),
V26 = (90, "V26"),
V27 = (91, "V27"),
V28 = (92, "V28"),
V29 = (93, "V29"),
V30 = (94, "V30"),
V31 = (95, "V31"),
Z0 = (96, "Z0"),
Z1 = (97, "Z1"),
Z2 = (98, "Z2"),
Z3 = (99, "Z3"),
Z4 = (100, "Z4"),
Z5 = (101, "Z5"),
Z6 = (102, "Z6"),
Z7 = (103, "Z7"),
Z8 = (104, "Z8"),
Z9 = (105, "Z9"),
Z10 = (106, "Z10"),
Z11 = (107, "Z11"),
Z12 = (108, "Z12"),
Z13 = (109, "Z13"),
Z14 = (110, "Z14"),
Z15 = (111, "Z15"),
Z16 = (112, "Z16"),
Z17 = (113, "Z17"),
Z18 = (114, "Z18"),
Z19 = (115, "Z19"),
Z20 = (116, "Z20"),
Z21 = (117, "Z21"),
Z22 = (118, "Z22"),
Z23 = (119, "Z23"),
Z24 = (120, "Z24"),
Z25 = (121, "Z25"),
Z26 = (122, "Z26"),
Z27 = (123, "Z27"),
Z28 = (124, "Z28"),
Z29 = (125, "Z29"),
Z30 = (126, "Z30"),
Z31 = (127, "Z31"),
});
/// LoongArch architecture specific definitions.
///
/// See [LoongArch ELF psABI specification](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html).
#[derive(Debug, Clone, Copy)]
pub struct LoongArch;
registers!(LoongArch, {
R0 = (0, "$r0"),
R1 = (1, "$r1"),
R2 = (2, "$r2"),
R3 = (3, "$r3"),
R4 = (4, "$r4"),
R5 = (5, "$r5"),
R6 = (6, "$r6"),
R7 = (7, "$r7"),
R8 = (8, "$r8"),
R9 = (9, "$r9"),
R10 = (10, "$r10"),
R11 = (11, "$r11"),
R12 = (12, "$r12"),
R13 = (13, "$r13"),
R14 = (14, "$r14"),
R15 = (15, "$r15"),
R16 = (16, "$r16"),
R17 = (17, "$r17"),
R18 = (18, "$r18"),
R19 = (19, "$r19"),
R20 = (20, "$r20"),
R21 = (21, "$r21"),
R22 = (22, "$r22"),
R23 = (23, "$r23"),
R24 = (24, "$r24"),
R25 = (25, "$r25"),
R26 = (26, "$r26"),
R27 = (27, "$r27"),
R28 = (28, "$r28"),
R29 = (29, "$r29"),
R30 = (30, "$r30"),
R31 = (31, "$r31"),
F0 = (32, "$f0"),
F1 = (33, "$f1"),
F2 = (34, "$f2"),
F3 = (35, "$f3"),
F4 = (36, "$f4"),
F5 = (37, "$f5"),
F6 = (38, "$f6"),
F7 = (39, "$f7"),
F8 = (40, "$f8"),
F9 = (41, "$f9"),
F10 = (42, "$f10"),
F11 = (43, "$f11"),
F12 = (44, "$f12"),
F13 = (45, "$f13"),
F14 = (46, "$f14"),
F15 = (47, "$f15"),
F16 = (48, "$f16"),
F17 = (49, "$f17"),
F18 = (50, "$f18"),
F19 = (51, "$f19"),
F20 = (52, "$f20"),
F21 = (53, "$f21"),
F22 = (54, "$f22"),
F23 = (55, "$f23"),
F24 = (56, "$f24"),
F25 = (57, "$f25"),
F26 = (58, "$f26"),
F27 = (59, "$f27"),
F28 = (60, "$f28"),
F29 = (61, "$f29"),
F30 = (62, "$f30"),
F31 = (63, "$f31"),
FCC0 = (64, "$fcc0"),
FCC1 = (65, "$fcc1"),
FCC2 = (66, "$fcc2"),
FCC3 = (67, "$fcc3"),
FCC4 = (68, "$fcc4"),
FCC5 = (69, "$fcc5"),
FCC6 = (70, "$fcc6"),
FCC7 = (71, "$fcc7"),
},
aliases {
ZERO = (0, "$zero"),
RA = (1, "$ra"),
TP = (2, "$tp"),
SP = (3, "$sp"),
A0 = (4, "$a0"),
A1 = (5, "$a1"),
A2 = (6, "$a2"),
A3 = (7, "$a3"),
A4 = (8, "$a4"),
A5 = (9, "$a5"),
A6 = (10, "$a6"),
A7 = (11, "$a7"),
T0 = (12, "$t0"),
T1 = (13, "$t1"),
T2 = (14, "$t2"),
T3 = (15, "$t3"),
T4 = (16, "$t4"),
T5 = (17, "$t5"),
T6 = (18, "$t6"),
T7 = (19, "$t7"),
T8 = (20, "$t8"),
FP = (22, "$fp"),
S0 = (23, "$s0"),
S1 = (24, "$s1"),
S2 = (25, "$s2"),
S3 = (26, "$s3"),
S4 = (27, "$s4"),
S5 = (28, "$s5"),
S6 = (29, "$s6"),
S7 = (30, "$s7"),
S8 = (31, "$s8"),
FA0 = (32, "$fa0"),
FA1 = (33, "$fa1"),
FA2 = (34, "$fa2"),
FA3 = (35, "$fa3"),
FA4 = (36, "$fa4"),
FA5 = (37, "$fa5"),
FA6 = (38, "$fa6"),
FA7 = (39, "$fa7"),
FT0 = (40, "$ft0"),
FT1 = (41, "$ft1"),
FT2 = (42, "$ft2"),
FT3 = (43, "$ft3"),
FT4 = (44, "$ft4"),
FT5 = (45, "$ft5"),
FT6 = (46, "$ft6"),
FT7 = (47, "$ft7"),
FT8 = (48, "$ft8"),
FT9 = (49, "$ft9"),
FT10 = (50, "$ft10"),
FT11 = (51, "$ft11"),
FT12 = (52, "$ft12"),
FT13 = (53, "$ft13"),
FT14 = (54, "$ft14"),
FT15 = (55, "$ft15"),
FS0 = (56, "$fs0"),
FS1 = (57, "$fs1"),
FS2 = (58, "$fs2"),
FS3 = (59, "$fs3"),
FS4 = (60, "$fs4"),
FS5 = (61, "$fs5"),
FS6 = (62, "$fs6"),
FS7 = (63, "$fs7"),
});
/// RISC-V architecture specific definitions.
///
/// See [RISC-V ELF psABI specification](https://github.com/riscv/riscv-elf-psabi-doc).
#[derive(Debug, Clone, Copy)]
pub struct RiscV;
registers!(RiscV, {
X0 = (0, "x0"),
X1 = (1, "x1"),
X2 = (2, "x2"),
X3 = (3, "x3"),
X4 = (4, "x4"),
X5 = (5, "x5"),
X6 = (6, "x6"),
X7 = (7, "x7"),
X8 = (8, "x8"),
X9 = (9, "x9"),
X10 = (10, "x10"),
X11 = (11, "x11"),
X12 = (12, "x12"),
X13 = (13, "x13"),
X14 = (14, "x14"),
X15 = (15, "x15"),
X16 = (16, "x16"),
X17 = (17, "x17"),
X18 = (18, "x18"),
X19 = (19, "x19"),
X20 = (20, "x20"),
X21 = (21, "x21"),
X22 = (22, "x22"),
X23 = (23, "x23"),
X24 = (24, "x24"),
X25 = (25, "x25"),
X26 = (26, "x26"),
X27 = (27, "x27"),
X28 = (28, "x28"),
X29 = (29, "x29"),
X30 = (30, "x30"),
X31 = (31, "x31"),
F0 = (32, "f0"),
F1 = (33, "f1"),
F2 = (34, "f2"),
F3 = (35, "f3"),
F4 = (36, "f4"),
F5 = (37, "f5"),
F6 = (38, "f6"),
F7 = (39, "f7"),
F8 = (40, "f8"),
F9 = (41, "f9"),
F10 = (42, "f10"),
F11 = (43, "f11"),
F12 = (44, "f12"),
F13 = (45, "f13"),
F14 = (46, "f14"),
F15 = (47, "f15"),
F16 = (48, "f16"),
F17 = (49, "f17"),
F18 = (50, "f18"),
F19 = (51, "f19"),
F20 = (52, "f20"),
F21 = (53, "f21"),
F22 = (54, "f22"),
F23 = (55, "f23"),
F24 = (56, "f24"),
F25 = (57, "f25"),
F26 = (58, "f26"),
F27 = (59, "f27"),
F28 = (60, "f28"),
F29 = (61, "f29"),
F30 = (62, "f30"),
F31 = (63, "f31"),
},
aliases {
ZERO = (0, "zero"),
RA = (1, "ra"),
SP = (2, "sp"),
GP = (3, "gp"),
TP = (4, "tp"),
T0 = (5, "t0"),
T1 = (6, "t1"),
T2 = (7, "t2"),
S0 = (8, "s0"),
S1 = (9, "s1"),
A0 = (10, "a0"),
A1 = (11, "a1"),
A2 = (12, "a2"),
A3 = (13, "a3"),
A4 = (14, "a4"),
A5 = (15, "a5"),
A6 = (16, "a6"),
A7 = (17, "a7"),
S2 = (18, "s2"),
S3 = (19, "s3"),
S4 = (20, "s4"),
S5 = (21, "s5"),
S6 = (22, "s6"),
S7 = (23, "s7"),
S8 = (24, "s8"),
S9 = (25, "s9"),
S10 = (26, "s10"),
S11 = (27, "s11"),
T3 = (28, "t3"),
T4 = (29, "t4"),
T5 = (30, "t5"),
T6 = (31, "t6"),
FT0 = (32, "ft0"),
FT1 = (33, "ft1"),
FT2 = (34, "ft2"),
FT3 = (35, "ft3"),
FT4 = (36, "ft4"),
FT5 = (37, "ft5"),
FT6 = (38, "ft6"),
FT7 = (39, "ft7"),
FS0 = (40, "fs0"),
FS1 = (41, "fs1"),
FA0 = (42, "fa0"),
FA1 = (43, "fa1"),
FA2 = (44, "fa2"),
FA3 = (45, "fa3"),
FA4 = (46, "fa4"),
FA5 = (47, "fa5"),
FA6 = (48, "fa6"),
FA7 = (49, "fa7"),
FS2 = (50, "fs2"),
FS3 = (51, "fs3"),
FS4 = (52, "fs4"),
FS5 = (53, "fs5"),
FS6 = (54, "fs6"),
FS7 = (55, "fs7"),
FS8 = (56, "fs8"),
FS9 = (57, "fs9"),
FS10 = (58, "fs10"),
FS11 = (59, "fs11"),
FT8 = (60, "ft8"),
FT9 = (61, "ft9"),
FT10 = (62, "ft10"),
FT11 = (63, "ft11"),
});
/// Intel i386 architecture specific definitions.
///
/// See Intel386 psABi version 1.1 at the [X86 psABI wiki](https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI).
#[derive(Debug, Clone, Copy)]
pub struct X86;
registers!(X86, {
EAX = (0, "eax"),
ECX = (1, "ecx"),
EDX = (2, "edx"),
EBX = (3, "ebx"),
ESP = (4, "esp"),
EBP = (5, "ebp"),
ESI = (6, "esi"),
EDI = (7, "edi"),
// Return Address register. This is stored in `0(%esp, "")` and is not a physical register.
RA = (8, "RA"),
ST0 = (11, "st0"),
ST1 = (12, "st1"),
ST2 = (13, "st2"),
ST3 = (14, "st3"),
ST4 = (15, "st4"),
ST5 = (16, "st5"),
ST6 = (17, "st6"),
ST7 = (18, "st7"),
XMM0 = (21, "xmm0"),
XMM1 = (22, "xmm1"),
XMM2 = (23, "xmm2"),
XMM3 = (24, "xmm3"),
XMM4 = (25, "xmm4"),
XMM5 = (26, "xmm5"),
XMM6 = (27, "xmm6"),
XMM7 = (28, "xmm7"),
MM0 = (29, "mm0"),
MM1 = (30, "mm1"),
MM2 = (31, "mm2"),
MM3 = (32, "mm3"),
MM4 = (33, "mm4"),
MM5 = (34, "mm5"),
MM6 = (35, "mm6"),
MM7 = (36, "mm7"),
MXCSR = (39, "mxcsr"),
ES = (40, "es"),
CS = (41, "cs"),
SS = (42, "ss"),
DS = (43, "ds"),
FS = (44, "fs"),
GS = (45, "gs"),
TR = (48, "tr"),
LDTR = (49, "ldtr"),
FS_BASE = (93, "fs.base"),
GS_BASE = (94, "gs.base"),
});
/// AMD64 architecture specific definitions.
///
/// See x86-64 psABI version 1.0 at the [X86 psABI wiki](https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI).
#[derive(Debug, Clone, Copy)]
pub struct X86_64;
registers!(X86_64, {
RAX = (0, "rax"),
RDX = (1, "rdx"),
RCX = (2, "rcx"),
RBX = (3, "rbx"),
RSI = (4, "rsi"),
RDI = (5, "rdi"),
RBP = (6, "rbp"),
RSP = (7, "rsp"),
R8 = (8, "r8"),
R9 = (9, "r9"),
R10 = (10, "r10"),
R11 = (11, "r11"),
R12 = (12, "r12"),
R13 = (13, "r13"),
R14 = (14, "r14"),
R15 = (15, "r15"),
// Return Address register. This is stored in `0(%rsp, "")` and is not a physical register.
RA = (16, "RA"),
XMM0 = (17, "xmm0"),
XMM1 = (18, "xmm1"),
XMM2 = (19, "xmm2"),
XMM3 = (20, "xmm3"),
XMM4 = (21, "xmm4"),
XMM5 = (22, "xmm5"),
XMM6 = (23, "xmm6"),
XMM7 = (24, "xmm7"),
XMM8 = (25, "xmm8"),
XMM9 = (26, "xmm9"),
XMM10 = (27, "xmm10"),
XMM11 = (28, "xmm11"),
XMM12 = (29, "xmm12"),
XMM13 = (30, "xmm13"),
XMM14 = (31, "xmm14"),
XMM15 = (32, "xmm15"),
ST0 = (33, "st0"),
ST1 = (34, "st1"),
ST2 = (35, "st2"),
ST3 = (36, "st3"),
ST4 = (37, "st4"),
ST5 = (38, "st5"),
ST6 = (39, "st6"),
ST7 = (40, "st7"),
MM0 = (41, "mm0"),
MM1 = (42, "mm1"),
MM2 = (43, "mm2"),
MM3 = (44, "mm3"),
MM4 = (45, "mm4"),
MM5 = (46, "mm5"),
MM6 = (47, "mm6"),
MM7 = (48, "mm7"),
RFLAGS = (49, "rFLAGS"),
ES = (50, "es"),
CS = (51, "cs"),
SS = (52, "ss"),
DS = (53, "ds"),
FS = (54, "fs"),
GS = (55, "gs"),
FS_BASE = (58, "fs.base"),
GS_BASE = (59, "gs.base"),
TR = (62, "tr"),
LDTR = (63, "ldtr"),
MXCSR = (64, "mxcsr"),
FCW = (65, "fcw"),
FSW = (66, "fsw"),
XMM16 = (67, "xmm16"),
XMM17 = (68, "xmm17"),
XMM18 = (69, "xmm18"),
XMM19 = (70, "xmm19"),
XMM20 = (71, "xmm20"),
XMM21 = (72, "xmm21"),
XMM22 = (73, "xmm22"),
XMM23 = (74, "xmm23"),
XMM24 = (75, "xmm24"),
XMM25 = (76, "xmm25"),
XMM26 = (77, "xmm26"),
XMM27 = (78, "xmm27"),
XMM28 = (79, "xmm28"),
XMM29 = (80, "xmm29"),
XMM30 = (81, "xmm30"),
XMM31 = (82, "xmm31"),
K0 = (118, "k0"),
K1 = (119, "k1"),
K2 = (120, "k2"),
K3 = (121, "k3"),
K4 = (122, "k4"),
K5 = (123, "k5"),
K6 = (124, "k6"),
K7 = (125, "k7"),
});
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "std")]
fn test_aarch64_registers() {
use super::*;
use std::collections::HashSet;
let mut names = HashSet::new();
for n in (0..=39).chain(46..=127) {
let name = AArch64::register_name(Register(n))
.unwrap_or_else(|| panic!("Register {} should have a name.", n));
assert!(names.insert(name));
}
}
}

391
vendor/gimli/src/common.rs vendored Normal file
View File

@ -0,0 +1,391 @@
/// Whether the format of a compilation unit is 32- or 64-bit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Format {
/// 64-bit DWARF
Dwarf64 = 8,
/// 32-bit DWARF
Dwarf32 = 4,
}
impl Format {
/// Return the serialized size of an initial length field for the format.
#[inline]
pub fn initial_length_size(self) -> u8 {
match self {
Format::Dwarf32 => 4,
Format::Dwarf64 => 12,
}
}
/// Return the natural word size for the format
#[inline]
pub fn word_size(self) -> u8 {
match self {
Format::Dwarf32 => 4,
Format::Dwarf64 => 8,
}
}
}
/// Which vendor extensions to support.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Vendor {
/// A default set of extensions, including some common GNU extensions.
Default,
/// AAarch64 extensions.
AArch64,
}
/// Encoding parameters that are commonly used for multiple DWARF sections.
///
/// This is intended to be small enough to pass by value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
// `address_size` and `format` are used more often than `version`, so keep
// them first.
#[repr(C)]
pub struct Encoding {
/// The size of an address.
pub address_size: u8,
// The size of a segment selector.
// TODO: pub segment_size: u8,
/// Whether the DWARF format is 32- or 64-bit.
pub format: Format,
/// The DWARF version of the header.
pub version: u16,
}
/// Encoding parameters for a line number program.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LineEncoding {
/// The size in bytes of the smallest target machine instruction.
pub minimum_instruction_length: u8,
/// The maximum number of individual operations that may be encoded in an
/// instruction.
pub maximum_operations_per_instruction: u8,
/// The initial value of the `is_stmt` register.
pub default_is_stmt: bool,
/// The minimum value which a special opcode can add to the line register.
pub line_base: i8,
/// The range of values which a special opcode can add to the line register.
pub line_range: u8,
}
impl Default for LineEncoding {
fn default() -> Self {
// Values from LLVM.
LineEncoding {
minimum_instruction_length: 1,
maximum_operations_per_instruction: 1,
default_is_stmt: true,
line_base: -5,
line_range: 14,
}
}
}
/// A DWARF register number.
///
/// The meaning of this value is ABI dependent. This is generally encoded as
/// a ULEB128, but supported architectures need 16 bits at most.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Register(pub u16);
/// An offset into the `.debug_abbrev` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugAbbrevOffset<T = usize>(pub T);
/// An offset to a set of entries in the `.debug_addr` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugAddrBase<T = usize>(pub T);
/// An index into a set of addresses in the `.debug_addr` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugAddrIndex<T = usize>(pub T);
/// An offset into the `.debug_aranges` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugArangesOffset<T = usize>(pub T);
/// An offset into the `.debug_info` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct DebugInfoOffset<T = usize>(pub T);
/// An offset into the `.debug_line` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLineOffset<T = usize>(pub T);
/// An offset into the `.debug_line_str` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLineStrOffset<T = usize>(pub T);
/// An offset into either the `.debug_loc` section or the `.debug_loclists` section,
/// depending on the version of the unit the offset was contained in.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocationListsOffset<T = usize>(pub T);
/// An offset to a set of location list offsets in the `.debug_loclists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLocListsBase<T = usize>(pub T);
/// An index into a set of location list offsets in the `.debug_loclists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugLocListsIndex<T = usize>(pub T);
/// An offset into the `.debug_macinfo` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugMacinfoOffset<T = usize>(pub T);
/// An offset into the `.debug_macro` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugMacroOffset<T = usize>(pub T);
/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section,
/// depending on the version of the unit the offset was contained in.
///
/// If this is from a DWARF 4 DWO file, then it must additionally be offset by the
/// value of `DW_AT_GNU_ranges_base`. You can use `Dwarf::ranges_offset_from_raw` to do this.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RawRangeListsOffset<T = usize>(pub T);
/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section,
/// depending on the version of the unit the offset was contained in.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RangeListsOffset<T = usize>(pub T);
/// An offset to a set of range list offsets in the `.debug_rnglists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugRngListsBase<T = usize>(pub T);
/// An index into a set of range list offsets in the `.debug_rnglists` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugRngListsIndex<T = usize>(pub T);
/// An offset into the `.debug_str` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffset<T = usize>(pub T);
/// An offset to a set of entries in the `.debug_str_offsets` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffsetsBase<T = usize>(pub T);
/// An index into a set of entries in the `.debug_str_offsets` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugStrOffsetsIndex<T = usize>(pub T);
/// An offset into the `.debug_types` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct DebugTypesOffset<T = usize>(pub T);
/// A type signature as used in the `.debug_types` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugTypeSignature(pub u64);
/// An offset into the `.debug_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugFrameOffset<T = usize>(pub T);
impl<T> From<T> for DebugFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
DebugFrameOffset(o)
}
}
/// An offset into the `.eh_frame` section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EhFrameOffset<T = usize>(pub T);
impl<T> From<T> for EhFrameOffset<T> {
#[inline]
fn from(o: T) -> Self {
EhFrameOffset(o)
}
}
/// An offset into the `.debug_info` or `.debug_types` sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum UnitSectionOffset<T = usize> {
/// An offset into the `.debug_info` section.
DebugInfoOffset(DebugInfoOffset<T>),
/// An offset into the `.debug_types` section.
DebugTypesOffset(DebugTypesOffset<T>),
}
impl<T> From<DebugInfoOffset<T>> for UnitSectionOffset<T> {
fn from(offset: DebugInfoOffset<T>) -> Self {
UnitSectionOffset::DebugInfoOffset(offset)
}
}
impl<T> From<DebugTypesOffset<T>> for UnitSectionOffset<T> {
fn from(offset: DebugTypesOffset<T>) -> Self {
UnitSectionOffset::DebugTypesOffset(offset)
}
}
impl<T> UnitSectionOffset<T>
where
T: Clone,
{
/// Returns the `DebugInfoOffset` inside, or `None` otherwise.
pub fn as_debug_info_offset(&self) -> Option<DebugInfoOffset<T>> {
match self {
UnitSectionOffset::DebugInfoOffset(offset) => Some(offset.clone()),
UnitSectionOffset::DebugTypesOffset(_) => None,
}
}
/// Returns the `DebugTypesOffset` inside, or `None` otherwise.
pub fn as_debug_types_offset(&self) -> Option<DebugTypesOffset<T>> {
match self {
UnitSectionOffset::DebugInfoOffset(_) => None,
UnitSectionOffset::DebugTypesOffset(offset) => Some(offset.clone()),
}
}
}
/// An identifier for a DWARF section.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum SectionId {
/// The `.debug_abbrev` section.
DebugAbbrev,
/// The `.debug_addr` section.
DebugAddr,
/// The `.debug_aranges` section.
DebugAranges,
/// The `.debug_cu_index` section.
DebugCuIndex,
/// The `.debug_frame` section.
DebugFrame,
/// The `.eh_frame` section.
EhFrame,
/// The `.eh_frame_hdr` section.
EhFrameHdr,
/// The `.debug_info` section.
DebugInfo,
/// The `.debug_line` section.
DebugLine,
/// The `.debug_line_str` section.
DebugLineStr,
/// The `.debug_loc` section.
DebugLoc,
/// The `.debug_loclists` section.
DebugLocLists,
/// The `.debug_macinfo` section.
DebugMacinfo,
/// The `.debug_macro` section.
DebugMacro,
/// The `.debug_pubnames` section.
DebugPubNames,
/// The `.debug_pubtypes` section.
DebugPubTypes,
/// The `.debug_ranges` section.
DebugRanges,
/// The `.debug_rnglists` section.
DebugRngLists,
/// The `.debug_str` section.
DebugStr,
/// The `.debug_str_offsets` section.
DebugStrOffsets,
/// The `.debug_tu_index` section.
DebugTuIndex,
/// The `.debug_types` section.
DebugTypes,
}
impl SectionId {
/// Returns the ELF section name for this kind.
pub fn name(self) -> &'static str {
match self {
SectionId::DebugAbbrev => ".debug_abbrev",
SectionId::DebugAddr => ".debug_addr",
SectionId::DebugAranges => ".debug_aranges",
SectionId::DebugCuIndex => ".debug_cu_index",
SectionId::DebugFrame => ".debug_frame",
SectionId::EhFrame => ".eh_frame",
SectionId::EhFrameHdr => ".eh_frame_hdr",
SectionId::DebugInfo => ".debug_info",
SectionId::DebugLine => ".debug_line",
SectionId::DebugLineStr => ".debug_line_str",
SectionId::DebugLoc => ".debug_loc",
SectionId::DebugLocLists => ".debug_loclists",
SectionId::DebugMacinfo => ".debug_macinfo",
SectionId::DebugMacro => ".debug_macro",
SectionId::DebugPubNames => ".debug_pubnames",
SectionId::DebugPubTypes => ".debug_pubtypes",
SectionId::DebugRanges => ".debug_ranges",
SectionId::DebugRngLists => ".debug_rnglists",
SectionId::DebugStr => ".debug_str",
SectionId::DebugStrOffsets => ".debug_str_offsets",
SectionId::DebugTuIndex => ".debug_tu_index",
SectionId::DebugTypes => ".debug_types",
}
}
/// Returns the ELF section name for this kind, when found in a .dwo or .dwp file.
pub fn dwo_name(self) -> Option<&'static str> {
Some(match self {
SectionId::DebugAbbrev => ".debug_abbrev.dwo",
SectionId::DebugCuIndex => ".debug_cu_index",
SectionId::DebugInfo => ".debug_info.dwo",
SectionId::DebugLine => ".debug_line.dwo",
// The debug_loc section can be present in the dwo when using the
// GNU split-dwarf extension to DWARF4.
SectionId::DebugLoc => ".debug_loc.dwo",
SectionId::DebugLocLists => ".debug_loclists.dwo",
SectionId::DebugMacro => ".debug_macro.dwo",
SectionId::DebugRngLists => ".debug_rnglists.dwo",
SectionId::DebugStr => ".debug_str.dwo",
SectionId::DebugStrOffsets => ".debug_str_offsets.dwo",
SectionId::DebugTuIndex => ".debug_tu_index",
SectionId::DebugTypes => ".debug_types.dwo",
_ => return None,
})
}
/// Returns the XCOFF section name for this kind.
pub fn xcoff_name(self) -> Option<&'static str> {
Some(match self {
SectionId::DebugAbbrev => ".dwabrev",
SectionId::DebugAranges => ".dwarnge",
SectionId::DebugFrame => ".dwframe",
SectionId::DebugInfo => ".dwinfo",
SectionId::DebugLine => ".dwline",
SectionId::DebugLoc => ".dwloc",
SectionId::DebugMacinfo => ".dwmac",
SectionId::DebugPubNames => ".dwpbnms",
SectionId::DebugPubTypes => ".dwpbtyp",
SectionId::DebugRanges => ".dwrnges",
SectionId::DebugStr => ".dwstr",
_ => return None,
})
}
}
/// An optionally-provided implementation-defined compilation unit ID to enable
/// split DWARF and linking a split compilation unit back together.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DwoId(pub u64);
/// The "type" of file with DWARF debugging information. This determines, among other things,
/// which files DWARF sections should be loaded from.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DwarfFileType {
/// A normal executable or object file.
Main,
/// A .dwo split DWARF file.
Dwo,
// TODO: Supplementary files, .dwps?
}
impl Default for DwarfFileType {
fn default() -> Self {
DwarfFileType::Main
}
}

1435
vendor/gimli/src/constants.rs vendored Normal file

File diff suppressed because it is too large Load Diff

256
vendor/gimli/src/endianity.rs vendored Normal file
View File

@ -0,0 +1,256 @@
//! Types for compile-time and run-time endianity.
use core::convert::TryInto;
use core::fmt::Debug;
/// A trait describing the endianity of some buffer.
pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq {
/// Return true for big endian byte order.
fn is_big_endian(self) -> bool;
/// Return true for little endian byte order.
#[inline]
fn is_little_endian(self) -> bool {
!self.is_big_endian()
}
/// Reads an unsigned 16 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 2`.
#[inline]
fn read_u16(self, buf: &[u8]) -> u16 {
let bytes: &[u8; 2] = buf[..2].try_into().unwrap();
if self.is_big_endian() {
u16::from_be_bytes(*bytes)
} else {
u16::from_le_bytes(*bytes)
}
}
/// Reads an unsigned 32 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 4`.
#[inline]
fn read_u32(self, buf: &[u8]) -> u32 {
let bytes: &[u8; 4] = buf[..4].try_into().unwrap();
if self.is_big_endian() {
u32::from_be_bytes(*bytes)
} else {
u32::from_le_bytes(*bytes)
}
}
/// Reads an unsigned 64 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_u64(self, buf: &[u8]) -> u64 {
let bytes: &[u8; 8] = buf[..8].try_into().unwrap();
if self.is_big_endian() {
u64::from_be_bytes(*bytes)
} else {
u64::from_le_bytes(*bytes)
}
}
/// Read an unsigned n-bytes integer u64.
///
/// # Panics
///
/// Panics when `buf.len() < 1` or `buf.len() > 8`.
#[inline]
fn read_uint(&mut self, buf: &[u8]) -> u64 {
let mut tmp = [0; 8];
if self.is_big_endian() {
tmp[8 - buf.len()..].copy_from_slice(buf);
} else {
tmp[..buf.len()].copy_from_slice(buf);
}
self.read_u64(&tmp)
}
/// Reads a signed 16 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 2`.
#[inline]
fn read_i16(self, buf: &[u8]) -> i16 {
self.read_u16(buf) as i16
}
/// Reads a signed 32 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 4`.
#[inline]
fn read_i32(self, buf: &[u8]) -> i32 {
self.read_u32(buf) as i32
}
/// Reads a signed 64 bit integer from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_i64(self, buf: &[u8]) -> i64 {
self.read_u64(buf) as i64
}
/// Reads a 32 bit floating point number from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_f32(self, buf: &[u8]) -> f32 {
f32::from_bits(self.read_u32(buf))
}
/// Reads a 32 bit floating point number from `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 8`.
#[inline]
fn read_f64(self, buf: &[u8]) -> f64 {
f64::from_bits(self.read_u64(buf))
}
/// Writes an unsigned 16 bit integer `n` to `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 2`.
#[inline]
fn write_u16(self, buf: &mut [u8], n: u16) {
let bytes = if self.is_big_endian() {
n.to_be_bytes()
} else {
n.to_le_bytes()
};
buf[..2].copy_from_slice(&bytes);
}
/// Writes an unsigned 32 bit integer `n` to `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 4`.
#[inline]
fn write_u32(self, buf: &mut [u8], n: u32) {
let bytes = if self.is_big_endian() {
n.to_be_bytes()
} else {
n.to_le_bytes()
};
buf[..4].copy_from_slice(&bytes);
}
/// Writes an unsigned 64 bit integer `n` to `buf`.
///
/// # Panics
///
/// Panics when `buf.len() < 8`.
#[inline]
fn write_u64(self, buf: &mut [u8], n: u64) {
let bytes = if self.is_big_endian() {
n.to_be_bytes()
} else {
n.to_le_bytes()
};
buf[..8].copy_from_slice(&bytes);
}
}
/// Byte order that is selectable at runtime.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RunTimeEndian {
/// Little endian byte order.
Little,
/// Big endian byte order.
Big,
}
impl Default for RunTimeEndian {
#[cfg(target_endian = "little")]
#[inline]
fn default() -> RunTimeEndian {
RunTimeEndian::Little
}
#[cfg(target_endian = "big")]
#[inline]
fn default() -> RunTimeEndian {
RunTimeEndian::Big
}
}
impl Endianity for RunTimeEndian {
#[inline]
fn is_big_endian(self) -> bool {
self != RunTimeEndian::Little
}
}
/// Little endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LittleEndian;
impl Default for LittleEndian {
#[inline]
fn default() -> LittleEndian {
LittleEndian
}
}
impl Endianity for LittleEndian {
#[inline]
fn is_big_endian(self) -> bool {
false
}
}
/// Big endian byte order.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BigEndian;
impl Default for BigEndian {
#[inline]
fn default() -> BigEndian {
BigEndian
}
}
impl Endianity for BigEndian {
#[inline]
fn is_big_endian(self) -> bool {
true
}
}
/// The native endianity for the target platform.
#[cfg(target_endian = "little")]
pub type NativeEndian = LittleEndian;
#[cfg(target_endian = "little")]
#[allow(non_upper_case_globals)]
#[doc(hidden)]
pub const NativeEndian: LittleEndian = LittleEndian;
/// The native endianity for the target platform.
#[cfg(target_endian = "big")]
pub type NativeEndian = BigEndian;
#[cfg(target_endian = "big")]
#[allow(non_upper_case_globals)]
#[doc(hidden)]
pub const NativeEndian: BigEndian = BigEndian;

612
vendor/gimli/src/leb128.rs vendored Normal file
View File

@ -0,0 +1,612 @@
//! Read and write DWARF's "Little Endian Base 128" (LEB128) variable length
//! integer encoding.
//!
//! The implementation is a direct translation of the psuedocode in the DWARF 4
//! standard's appendix C.
//!
//! Read and write signed integers:
//!
//! ```
//! # #[cfg(all(feature = "read", feature = "write"))] {
//! use gimli::{EndianSlice, NativeEndian, leb128};
//!
//! let mut buf = [0; 1024];
//!
//! // Write to anything that implements `std::io::Write`.
//! {
//! let mut writable = &mut buf[..];
//! leb128::write::signed(&mut writable, -12345).expect("Should write number");
//! }
//!
//! // Read from anything that implements `gimli::Reader`.
//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
//! let val = leb128::read::signed(&mut readable).expect("Should read number");
//! assert_eq!(val, -12345);
//! # }
//! ```
//!
//! Or read and write unsigned integers:
//!
//! ```
//! # #[cfg(all(feature = "read", feature = "write"))] {
//! use gimli::{EndianSlice, NativeEndian, leb128};
//!
//! let mut buf = [0; 1024];
//!
//! {
//! let mut writable = &mut buf[..];
//! leb128::write::unsigned(&mut writable, 98765).expect("Should write number");
//! }
//!
//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
//! let val = leb128::read::unsigned(&mut readable).expect("Should read number");
//! assert_eq!(val, 98765);
//! # }
//! ```
const CONTINUATION_BIT: u8 = 1 << 7;
#[cfg(feature = "read-core")]
const SIGN_BIT: u8 = 1 << 6;
#[inline]
fn low_bits_of_byte(byte: u8) -> u8 {
byte & !CONTINUATION_BIT
}
#[inline]
#[allow(dead_code)]
fn low_bits_of_u64(val: u64) -> u8 {
let byte = val & u64::from(core::u8::MAX);
low_bits_of_byte(byte as u8)
}
/// A module for reading signed and unsigned integers that have been LEB128
/// encoded.
#[cfg(feature = "read-core")]
pub mod read {
use super::{low_bits_of_byte, CONTINUATION_BIT, SIGN_BIT};
use crate::read::{Error, Reader, Result};
/// Read bytes until the LEB128 continuation bit is not set.
pub fn skip<R: Reader>(r: &mut R) -> Result<()> {
loop {
let byte = r.read_u8()?;
if byte & CONTINUATION_BIT == 0 {
return Ok(());
}
}
}
/// Read an unsigned LEB128 number from the given `Reader` and
/// return it or an error if reading failed.
pub fn unsigned<R: Reader>(r: &mut R) -> Result<u64> {
let mut result = 0;
let mut shift = 0;
loop {
let byte = r.read_u8()?;
if shift == 63 && byte != 0x00 && byte != 0x01 {
return Err(Error::BadUnsignedLeb128);
}
let low_bits = u64::from(low_bits_of_byte(byte));
result |= low_bits << shift;
if byte & CONTINUATION_BIT == 0 {
return Ok(result);
}
shift += 7;
}
}
/// Read an LEB128 u16 from the given `Reader` and
/// return it or an error if reading failed.
pub fn u16<R: Reader>(r: &mut R) -> Result<u16> {
let byte = r.read_u8()?;
let mut result = u16::from(low_bits_of_byte(byte));
if byte & CONTINUATION_BIT == 0 {
return Ok(result);
}
let byte = r.read_u8()?;
result |= u16::from(low_bits_of_byte(byte)) << 7;
if byte & CONTINUATION_BIT == 0 {
return Ok(result);
}
let byte = r.read_u8()?;
if byte > 0x03 {
return Err(Error::BadUnsignedLeb128);
}
result += u16::from(byte) << 14;
Ok(result)
}
/// Read a signed LEB128 number from the given `Reader` and
/// return it or an error if reading failed.
pub fn signed<R: Reader>(r: &mut R) -> Result<i64> {
let mut result = 0;
let mut shift = 0;
let size = 64;
let mut byte;
loop {
byte = r.read_u8()?;
if shift == 63 && byte != 0x00 && byte != 0x7f {
return Err(Error::BadSignedLeb128);
}
let low_bits = i64::from(low_bits_of_byte(byte));
result |= low_bits << shift;
shift += 7;
if byte & CONTINUATION_BIT == 0 {
break;
}
}
if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
// Sign extend the result.
result |= !0 << shift;
}
Ok(result)
}
}
/// A module for writing integers encoded as LEB128.
#[cfg(feature = "write")]
pub mod write {
use super::{low_bits_of_u64, CONTINUATION_BIT};
use std::io;
/// Write the given unsigned number using the LEB128 encoding to the given
/// `std::io::Write`able. Returns the number of bytes written to `w`, or an
/// error if writing failed.
pub fn unsigned<W>(w: &mut W, mut val: u64) -> Result<usize, io::Error>
where
W: io::Write,
{
let mut bytes_written = 0;
loop {
let mut byte = low_bits_of_u64(val);
val >>= 7;
if val != 0 {
// More bytes to come, so set the continuation bit.
byte |= CONTINUATION_BIT;
}
let buf = [byte];
w.write_all(&buf)?;
bytes_written += 1;
if val == 0 {
return Ok(bytes_written);
}
}
}
/// Return the size of the LEB128 encoding of the given unsigned number.
pub fn uleb128_size(mut val: u64) -> usize {
let mut size = 0;
loop {
val >>= 7;
size += 1;
if val == 0 {
return size;
}
}
}
/// Write the given signed number using the LEB128 encoding to the given
/// `std::io::Write`able. Returns the number of bytes written to `w`, or an
/// error if writing failed.
pub fn signed<W>(w: &mut W, mut val: i64) -> Result<usize, io::Error>
where
W: io::Write,
{
let mut bytes_written = 0;
loop {
let mut byte = val as u8;
// Keep the sign bit for testing
val >>= 6;
let done = val == 0 || val == -1;
if done {
byte &= !CONTINUATION_BIT;
} else {
// Remove the sign bit
val >>= 1;
// More bytes to come, so set the continuation bit.
byte |= CONTINUATION_BIT;
}
let buf = [byte];
w.write_all(&buf)?;
bytes_written += 1;
if done {
return Ok(bytes_written);
}
}
}
/// Return the size of the LEB128 encoding of the given signed number.
pub fn sleb128_size(mut val: i64) -> usize {
let mut size = 0;
loop {
val >>= 6;
let done = val == 0 || val == -1;
val >>= 1;
size += 1;
if done {
return size;
}
}
}
}
#[cfg(test)]
#[cfg(all(feature = "read", feature = "write"))]
mod tests {
use super::{low_bits_of_byte, low_bits_of_u64, read, write, CONTINUATION_BIT};
use crate::endianity::NativeEndian;
use crate::read::{EndianSlice, Error, ReaderOffsetId};
trait ResultExt {
fn map_eof(self, input: &[u8]) -> Self;
}
impl<T> ResultExt for Result<T, Error> {
fn map_eof(self, input: &[u8]) -> Self {
match self {
Err(Error::UnexpectedEof(id)) => {
let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
Err(Error::UnexpectedEof(id))
}
r => r,
}
}
}
#[test]
fn test_low_bits_of_byte() {
for i in 0..127 {
assert_eq!(i, low_bits_of_byte(i));
assert_eq!(i, low_bits_of_byte(i | CONTINUATION_BIT));
}
}
#[test]
fn test_low_bits_of_u64() {
for i in 0u64..127 {
assert_eq!(i as u8, low_bits_of_u64(1 << 16 | i));
assert_eq!(
i as u8,
low_bits_of_u64(i << 16 | i | (u64::from(CONTINUATION_BIT)))
);
}
}
// Examples from the DWARF 4 standard, section 7.6, figure 22.
#[test]
fn test_read_unsigned() {
let buf = [2u8];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
2,
read::unsigned(&mut readable).expect("Should read number")
);
let buf = [127u8];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
127,
read::unsigned(&mut readable).expect("Should read number")
);
let buf = [CONTINUATION_BIT, 1];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
128,
read::unsigned(&mut readable).expect("Should read number")
);
let buf = [1u8 | CONTINUATION_BIT, 1];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
129,
read::unsigned(&mut readable).expect("Should read number")
);
let buf = [2u8 | CONTINUATION_BIT, 1];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
130,
read::unsigned(&mut readable).expect("Should read number")
);
let buf = [57u8 | CONTINUATION_BIT, 100];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
12857,
read::unsigned(&mut readable).expect("Should read number")
);
}
// Examples from the DWARF 4 standard, section 7.6, figure 23.
#[test]
fn test_read_signed() {
let buf = [2u8];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(2, read::signed(&mut readable).expect("Should read number"));
let buf = [0x7eu8];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(-2, read::signed(&mut readable).expect("Should read number"));
let buf = [127u8 | CONTINUATION_BIT, 0];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
127,
read::signed(&mut readable).expect("Should read number")
);
let buf = [1u8 | CONTINUATION_BIT, 0x7f];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
-127,
read::signed(&mut readable).expect("Should read number")
);
let buf = [CONTINUATION_BIT, 1];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
128,
read::signed(&mut readable).expect("Should read number")
);
let buf = [CONTINUATION_BIT, 0x7f];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
-128,
read::signed(&mut readable).expect("Should read number")
);
let buf = [1u8 | CONTINUATION_BIT, 1];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
129,
read::signed(&mut readable).expect("Should read number")
);
let buf = [0x7fu8 | CONTINUATION_BIT, 0x7e];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
-129,
read::signed(&mut readable).expect("Should read number")
);
}
#[test]
fn test_read_signed_63_bits() {
let buf = [
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
CONTINUATION_BIT,
0x40,
];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
-0x4000_0000_0000_0000,
read::signed(&mut readable).expect("Should read number")
);
}
#[test]
fn test_read_unsigned_not_enough_data() {
let buf = [CONTINUATION_BIT];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
read::unsigned(&mut readable).map_eof(&buf),
Err(Error::UnexpectedEof(ReaderOffsetId(1)))
);
}
#[test]
fn test_read_signed_not_enough_data() {
let buf = [CONTINUATION_BIT];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
read::signed(&mut readable).map_eof(&buf),
Err(Error::UnexpectedEof(ReaderOffsetId(1)))
);
}
#[test]
fn test_write_unsigned_not_enough_space() {
let mut buf = [0; 1];
let mut writable = &mut buf[..];
match write::unsigned(&mut writable, 128) {
Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
otherwise => panic!("Unexpected: {:?}", otherwise),
}
}
#[test]
fn test_write_signed_not_enough_space() {
let mut buf = [0; 1];
let mut writable = &mut buf[..];
match write::signed(&mut writable, 128) {
Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
otherwise => panic!("Unexpected: {:?}", otherwise),
}
}
#[test]
fn dogfood_signed() {
fn inner(i: i64) {
let mut buf = [0u8; 1024];
{
let mut writable = &mut buf[..];
write::signed(&mut writable, i).expect("Should write signed number");
}
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
let result = read::signed(&mut readable).expect("Should be able to read it back again");
assert_eq!(i, result);
}
for i in -513..513 {
inner(i);
}
inner(core::i64::MIN);
}
#[test]
fn dogfood_unsigned() {
for i in 0..1025 {
let mut buf = [0u8; 1024];
{
let mut writable = &mut buf[..];
write::unsigned(&mut writable, i).expect("Should write signed number");
}
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
let result =
read::unsigned(&mut readable).expect("Should be able to read it back again");
assert_eq!(i, result);
}
}
#[test]
fn test_read_unsigned_overflow() {
let buf = [
2u8 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
1,
];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert!(read::unsigned(&mut readable).is_err());
}
#[test]
fn test_read_signed_overflow() {
let buf = [
2u8 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
2 | CONTINUATION_BIT,
1,
];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert!(read::signed(&mut readable).is_err());
}
#[test]
fn test_read_multiple() {
let buf = [2u8 | CONTINUATION_BIT, 1u8, 1u8];
let mut readable = EndianSlice::new(&buf[..], NativeEndian);
assert_eq!(
read::unsigned(&mut readable).expect("Should read first number"),
130u64
);
assert_eq!(
read::unsigned(&mut readable).expect("Should read first number"),
1u64
);
}
#[test]
fn test_read_u16() {
for (buf, val) in [
(&[2][..], 2),
(&[0x7f][..], 0x7f),
(&[0x80, 1][..], 0x80),
(&[0x81, 1][..], 0x81),
(&[0x82, 1][..], 0x82),
(&[0xff, 0x7f][..], 0x3fff),
(&[0x80, 0x80, 1][..], 0x4000),
(&[0xff, 0xff, 1][..], 0x7fff),
(&[0xff, 0xff, 3][..], 0xffff),
]
.iter()
{
let mut readable = EndianSlice::new(buf, NativeEndian);
assert_eq!(*val, read::u16(&mut readable).expect("Should read number"));
}
for buf in [
&[0x80][..],
&[0x80, 0x80][..],
&[0x80, 0x80, 4][..],
&[0x80, 0x80, 0x80, 3][..],
]
.iter()
{
let mut readable = EndianSlice::new(buf, NativeEndian);
assert!(read::u16(&mut readable).is_err(), "{:?}", buf);
}
}
}

79
vendor/gimli/src/lib.rs vendored Normal file
View File

@ -0,0 +1,79 @@
//! `gimli` is a library for reading and writing the
//! [DWARF debugging format](https://dwarfstd.org/).
//!
//! See the [read](./read/index.html) and [write](./write/index.html) modules
//! for examples and API documentation.
//!
//! ## Cargo Features
//!
//! Cargo features that can be enabled with `gimli`:
//!
//! * `std`: Enabled by default. Use the `std` library. Disabling this feature
//! allows using `gimli` in embedded environments that do not have access to
//! `std`. Note that even when `std` is disabled, `gimli` still requires an
//! implementation of the `alloc` crate.
//!
//! * `read`: Enabled by default. Enables the `read` module. Use of `std` is
//! optional.
//!
//! * `write`: Enabled by default. Enables the `write` module. Always uses
//! the `std` library.
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
// Selectively enable rust 2018 warnings
#![warn(bare_trait_objects)]
#![warn(unused_extern_crates)]
#![warn(ellipsis_inclusive_range_patterns)]
//#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
// Style.
#![allow(clippy::bool_to_int_with_if)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::comparison_chain)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::needless_late_init)]
#![allow(clippy::too_many_arguments)]
// False positives with `fallible_iterator`.
#![allow(clippy::should_implement_trait)]
// False positives.
#![allow(clippy::derive_partial_eq_without_eq)]
#![no_std]
#[allow(unused_imports)]
#[cfg(any(feature = "read", feature = "write"))]
#[macro_use]
extern crate alloc;
#[cfg(any(feature = "std", feature = "write"))]
#[macro_use]
extern crate std;
#[cfg(feature = "endian-reader")]
pub use stable_deref_trait::{CloneStableDeref, StableDeref};
mod common;
pub use crate::common::*;
mod arch;
pub use crate::arch::*;
pub mod constants;
// For backwards compat.
pub use crate::constants::*;
mod endianity;
pub use crate::endianity::*;
pub mod leb128;
#[cfg(feature = "read-core")]
pub mod read;
// For backwards compat.
#[cfg(feature = "read-core")]
pub use crate::read::*;
#[cfg(feature = "write")]
pub mod write;
#[cfg(test)]
mod test_util;

1102
vendor/gimli/src/read/abbrev.rs vendored Normal file

File diff suppressed because it is too large Load Diff

128
vendor/gimli/src/read/addr.rs vendored Normal file
View File

@ -0,0 +1,128 @@
use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
use crate::read::{Reader, ReaderOffset, Result, Section};
/// The raw contents of the `.debug_addr` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugAddr<R> {
section: R,
}
impl<R: Reader> DebugAddr<R> {
// TODO: add an iterator over the sets of addresses in the section.
// This is not needed for common usage of the section though.
/// Returns the address at the given `base` and `index`.
///
/// A set of addresses in the `.debug_addr` section consists of a header
/// followed by a series of addresses.
///
/// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
/// This is an offset that points to the first address following the header.
///
/// The `index` is the value of a `DW_FORM_addrx` attribute.
///
/// The `address_size` must be the size of the address for the compilation unit.
/// This value must also match the header. However, note that we do not parse the
/// header to validate this, since locating the header is unreliable, and the GNU
/// extensions do not emit it.
pub fn get_address(
&self,
address_size: u8,
base: DebugAddrBase<R::Offset>,
index: DebugAddrIndex<R::Offset>,
) -> Result<u64> {
let input = &mut self.section.clone();
input.skip(base.0)?;
input.skip(R::Offset::from_u64(
index.0.into_u64() * u64::from(address_size),
)?)?;
input.read_address(address_size)
}
}
impl<T> DebugAddr<T> {
/// Create a `DebugAddr` section that references the data in `self`.
///
/// This is useful when `R` implements `Reader` but `T` does not.
///
/// ## Example Usage
///
/// ```rust,no_run
/// # let load_section = || unimplemented!();
/// // Read the DWARF section into a `Vec` with whatever object loader you're using.
/// let owned_section: gimli::DebugAddr<Vec<u8>> = load_section();
/// // Create a reference to the DWARF section.
/// let section = owned_section.borrow(|section| {
/// gimli::EndianSlice::new(&section, gimli::LittleEndian)
/// });
/// ```
pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
impl<R> Section<R> for DebugAddr<R> {
fn id() -> SectionId {
SectionId::DebugAddr
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugAddr<R> {
fn from(section: R) -> Self {
DebugAddr { section }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read::EndianSlice;
use crate::test_util::GimliSectionMethods;
use crate::{Format, LittleEndian};
use test_assembler::{Endian, Label, LabelMaker, Section};
#[test]
fn test_get_address() {
for format in vec![Format::Dwarf32, Format::Dwarf64] {
for address_size in vec![4, 8] {
let zero = Label::new();
let length = Label::new();
let start = Label::new();
let first = Label::new();
let end = Label::new();
let mut section = Section::with_endian(Endian::Little)
.mark(&zero)
.initial_length(format, &length, &start)
.D16(5)
.D8(address_size)
.D8(0)
.mark(&first);
for i in 0..20 {
section = section.word(address_size, 1000 + i);
}
section = section.mark(&end);
length.set_const((&end - &start) as u64);
let section = section.get_contents().unwrap();
let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
let base = DebugAddrBase((&first - &zero) as usize);
assert_eq!(
debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
Ok(1000)
);
assert_eq!(
debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
Ok(1019)
);
}
}
}
}

660
vendor/gimli/src/read/aranges.rs vendored Normal file
View File

@ -0,0 +1,660 @@
use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
use crate::endianity::Endianity;
use crate::read::{EndianSlice, Error, Range, Reader, ReaderOffset, Result, Section};
/// The `DebugAranges` struct represents the DWARF address range information
/// found in the `.debug_aranges` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugAranges<R> {
section: R,
}
impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
/// section.
///
/// It is the caller's responsibility to read the `.debug_aranges` section and
/// present it as a `&[u8]` slice. That means using some ELF loader on
/// Linux, a Mach-O loader on macOS, etc.
///
/// ```
/// use gimli::{DebugAranges, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_aranges_section = || &buf;
/// let debug_aranges =
/// DebugAranges::new(read_debug_aranges_section(), LittleEndian);
/// ```
pub fn new(section: &'input [u8], endian: Endian) -> Self {
DebugAranges {
section: EndianSlice::new(section, endian),
}
}
}
impl<R: Reader> DebugAranges<R> {
/// Iterate the sets of entries in the `.debug_aranges` section.
///
/// Each set of entries belongs to a single unit.
pub fn headers(&self) -> ArangeHeaderIter<R> {
ArangeHeaderIter {
input: self.section.clone(),
offset: DebugArangesOffset(R::Offset::from_u8(0)),
}
}
/// Get the header at the given offset.
pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
let mut input = self.section.clone();
input.skip(offset.0)?;
ArangeHeader::parse(&mut input, offset)
}
}
impl<T> DebugAranges<T> {
/// Create a `DebugAranges` section that references the data in `self`.
///
/// This is useful when `R` implements `Reader` but `T` does not.
///
/// ## Example Usage
///
/// ```rust,no_run
/// # let load_section = || unimplemented!();
/// // Read the DWARF section into a `Vec` with whatever object loader you're using.
/// let owned_section: gimli::DebugAranges<Vec<u8>> = load_section();
/// // Create a reference to the DWARF section.
/// let section = owned_section.borrow(|section| {
/// gimli::EndianSlice::new(&section, gimli::LittleEndian)
/// });
/// ```
pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
impl<R> Section<R> for DebugAranges<R> {
fn id() -> SectionId {
SectionId::DebugAranges
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugAranges<R> {
fn from(section: R) -> Self {
DebugAranges { section }
}
}
/// An iterator over the headers of a `.debug_aranges` section.
#[derive(Clone, Debug)]
pub struct ArangeHeaderIter<R: Reader> {
input: R,
offset: DebugArangesOffset<R::Offset>,
}
impl<R: Reader> ArangeHeaderIter<R> {
/// Advance the iterator to the next header.
pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
if self.input.is_empty() {
return Ok(None);
}
let len = self.input.len();
match ArangeHeader::parse(&mut self.input, self.offset) {
Ok(header) => {
self.offset.0 += len - self.input.len();
Ok(Some(header))
}
Err(e) => {
self.input.empty();
Err(e)
}
}
}
}
#[cfg(feature = "fallible-iterator")]
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
type Item = ArangeHeader<R>;
type Error = Error;
fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
ArangeHeaderIter::next(self)
}
}
/// A header for a set of entries in the `.debug_arange` section.
///
/// These entries all belong to a single unit.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
where
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
offset: DebugArangesOffset<Offset>,
encoding: Encoding,
length: Offset,
debug_info_offset: DebugInfoOffset<Offset>,
segment_size: u8,
entries: R,
}
impl<R, Offset> ArangeHeader<R, Offset>
where
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
let (length, format) = input.read_initial_length()?;
let mut rest = input.split(length)?;
// Check the version. The DWARF 5 spec says that this is always 2, but version 3
// has been observed in the wild, potentially due to a bug; see
// https://github.com/gimli-rs/gimli/issues/559 for more information.
// lldb allows versions 2 through 5, possibly by mistake.
let version = rest.read_u16()?;
if version != 2 && version != 3 {
return Err(Error::UnknownVersion(u64::from(version)));
}
let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
let address_size = rest.read_u8()?;
let segment_size = rest.read_u8()?;
// unit_length + version + offset + address_size + segment_size
let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
// The first tuple following the header in each set begins at an offset that is
// a multiple of the size of a single tuple (that is, the size of a segment selector
// plus twice the size of an address).
let tuple_length = address_size
.checked_mul(2)
.and_then(|x| x.checked_add(segment_size))
.ok_or(Error::InvalidAddressRange)?;
if tuple_length == 0 {
return Err(Error::InvalidAddressRange)?;
}
let padding = if header_length % tuple_length == 0 {
0
} else {
tuple_length - header_length % tuple_length
};
rest.skip(R::Offset::from_u8(padding))?;
let encoding = Encoding {
format,
version,
address_size,
// TODO: segment_size
};
Ok(ArangeHeader {
offset,
encoding,
length,
debug_info_offset,
segment_size,
entries: rest,
})
}
/// Return the offset of this header within the `.debug_aranges` section.
#[inline]
pub fn offset(&self) -> DebugArangesOffset<Offset> {
self.offset
}
/// Return the length of this set of entries, including the header.
#[inline]
pub fn length(&self) -> Offset {
self.length
}
/// Return the encoding parameters for this set of entries.
#[inline]
pub fn encoding(&self) -> Encoding {
self.encoding
}
/// Return the segment size for this set of entries.
#[inline]
pub fn segment_size(&self) -> u8 {
self.segment_size
}
/// Return the offset into the .debug_info section for this set of arange entries.
#[inline]
pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
self.debug_info_offset
}
/// Return the arange entries in this set.
#[inline]
pub fn entries(&self) -> ArangeEntryIter<R> {
ArangeEntryIter {
input: self.entries.clone(),
encoding: self.encoding,
segment_size: self.segment_size,
}
}
}
/// An iterator over the aranges from a `.debug_aranges` section.
///
/// Can be [used with
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
#[derive(Debug, Clone)]
pub struct ArangeEntryIter<R: Reader> {
input: R,
encoding: Encoding,
segment_size: u8,
}
impl<R: Reader> ArangeEntryIter<R> {
/// Advance the iterator and return the next arange.
///
/// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
/// when iteration is complete and all aranges have already been parsed and
/// yielded. If an error occurs while parsing the next arange, then this error
/// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
if self.input.is_empty() {
return Ok(None);
}
match ArangeEntry::parse(&mut self.input, self.encoding, self.segment_size) {
Ok(Some(entry)) => Ok(Some(entry)),
Ok(None) => {
self.input.empty();
Ok(None)
}
Err(e) => {
self.input.empty();
Err(e)
}
}
}
}
#[cfg(feature = "fallible-iterator")]
impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
type Item = ArangeEntry;
type Error = Error;
fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
ArangeEntryIter::next(self)
}
}
/// A single parsed arange.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ArangeEntry {
segment: Option<u64>,
address: u64,
length: u64,
}
impl ArangeEntry {
/// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
fn parse<R: Reader>(
input: &mut R,
encoding: Encoding,
segment_size: u8,
) -> Result<Option<Self>> {
let address_size = encoding.address_size;
let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
if tuple_length > input.len() {
input.empty();
return Ok(None);
}
let segment = if segment_size != 0 {
input.read_address(segment_size)?
} else {
0
};
let address = input.read_address(address_size)?;
let length = input.read_address(address_size)?;
match (segment, address, length) {
// This is meant to be a null terminator, but in practice it can occur
// before the end, possibly due to a linker omitting a function and
// leaving an unrelocated entry.
(0, 0, 0) => Self::parse(input, encoding, segment_size),
_ => Ok(Some(ArangeEntry {
segment: if segment_size != 0 {
Some(segment)
} else {
None
},
address,
length,
})),
}
}
/// Return the segment selector of this arange.
#[inline]
pub fn segment(&self) -> Option<u64> {
self.segment
}
/// Return the beginning address of this arange.
#[inline]
pub fn address(&self) -> u64 {
self.address
}
/// Return the length of this arange.
#[inline]
pub fn length(&self) -> u64 {
self.length
}
/// Return the range.
#[inline]
pub fn range(&self) -> Range {
Range {
begin: self.address,
end: self.address.wrapping_add(self.length),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::common::{DebugInfoOffset, Format};
use crate::endianity::LittleEndian;
use crate::read::EndianSlice;
#[test]
fn test_iterate_headers() {
#[rustfmt::skip]
let buf = [
// 32-bit length = 28.
0x1c, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x01, 0x02, 0x03, 0x04,
// Address size.
0x04,
// Segment size.
0x00,
// Dummy padding and arange tuples.
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 32-bit length = 36.
0x24, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x11, 0x12, 0x13, 0x14,
// Address size.
0x04,
// Segment size.
0x00,
// Dummy padding and arange tuples.
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let debug_aranges = DebugAranges::new(&buf, LittleEndian);
let mut headers = debug_aranges.headers();
let header = headers
.next()
.expect("should parse header ok")
.expect("should have a header");
assert_eq!(header.offset(), DebugArangesOffset(0));
assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
let header = headers
.next()
.expect("should parse header ok")
.expect("should have a header");
assert_eq!(header.offset(), DebugArangesOffset(0x20));
assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
}
#[test]
fn test_parse_header_ok() {
#[rustfmt::skip]
let buf = [
// 32-bit length = 32.
0x20, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x01, 0x02, 0x03, 0x04,
// Address size.
0x08,
// Segment size.
0x04,
// Length to here = 12, tuple length = 20.
// Padding to tuple length multiple = 4.
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy arange tuple data.
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy next arange.
0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let header =
ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
assert_eq!(
*rest,
EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
);
assert_eq!(
header,
ArangeHeader {
offset: DebugArangesOffset(0x10),
encoding: Encoding {
format: Format::Dwarf32,
version: 2,
address_size: 8,
},
length: 0x20,
debug_info_offset: DebugInfoOffset(0x0403_0201),
segment_size: 4,
entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
}
);
}
#[test]
fn test_parse_header_overflow_error() {
#[rustfmt::skip]
let buf = [
// 32-bit length = 32.
0x20, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x01, 0x02, 0x03, 0x04,
// Address size.
0xff,
// Segment size.
0xff,
// Length to here = 12, tuple length = 20.
// Padding to tuple length multiple = 4.
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy arange tuple data.
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy next arange.
0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
.expect_err("should fail to parse header");
assert_eq!(error, Error::InvalidAddressRange);
}
#[test]
fn test_parse_header_div_by_zero_error() {
#[rustfmt::skip]
let buf = [
// 32-bit length = 32.
0x20, 0x00, 0x00, 0x00,
// Version.
0x02, 0x00,
// Offset.
0x01, 0x02, 0x03, 0x04,
// Address size = 0. Could cause a division by zero if we aren't
// careful.
0x00,
// Segment size.
0x00,
// Length to here = 12, tuple length = 20.
// Padding to tuple length multiple = 4.
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy arange tuple data.
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// Dummy next arange.
0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
.expect_err("should fail to parse header");
assert_eq!(error, Error::InvalidAddressRange);
}
#[test]
fn test_parse_entry_ok() {
let encoding = Encoding {
format: Format::Dwarf32,
version: 2,
address_size: 4,
};
let segment_size = 0;
let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: None,
address: 0x0403_0201,
length: 0x0807_0605,
})
);
}
#[test]
fn test_parse_entry_segment() {
let encoding = Encoding {
format: Format::Dwarf32,
version: 2,
address_size: 4,
};
let segment_size = 8;
#[rustfmt::skip]
let buf = [
// Segment.
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
// Address.
0x01, 0x02, 0x03, 0x04,
// Length.
0x05, 0x06, 0x07, 0x08,
// Next tuple.
0x09
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: Some(0x1817_1615_1413_1211),
address: 0x0403_0201,
length: 0x0807_0605,
})
);
}
#[test]
fn test_parse_entry_zero() {
let encoding = Encoding {
format: Format::Dwarf32,
version: 2,
address_size: 4,
};
let segment_size = 0;
#[rustfmt::skip]
let buf = [
// Zero tuple.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Address.
0x01, 0x02, 0x03, 0x04,
// Length.
0x05, 0x06, 0x07, 0x08,
// Next tuple.
0x09
];
let rest = &mut EndianSlice::new(&buf, LittleEndian);
let entry =
ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
assert_eq!(
entry,
Some(ArangeEntry {
segment: None,
address: 0x0403_0201,
length: 0x0807_0605,
})
);
}
}

7823
vendor/gimli/src/read/cfi.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1210
vendor/gimli/src/read/dwarf.rs vendored Normal file

File diff suppressed because it is too large Load Diff

639
vendor/gimli/src/read/endian_reader.rs vendored Normal file
View File

@ -0,0 +1,639 @@
//! Defining custom `Reader`s quickly.
use alloc::borrow::Cow;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::sync::Arc;
use core::fmt::Debug;
use core::ops::{Deref, Index, Range, RangeFrom, RangeTo};
use core::slice;
use core::str;
use stable_deref_trait::CloneStableDeref;
use crate::endianity::Endianity;
use crate::read::{Error, Reader, ReaderOffsetId, Result};
/// A reference counted, non-thread-safe slice of bytes and associated
/// endianity.
///
/// ```
/// # #[cfg(feature = "std")] {
/// use std::rc::Rc;
///
/// let buf = Rc::from(&[1, 2, 3, 4][..]);
/// let reader = gimli::EndianRcSlice::new(buf, gimli::NativeEndian);
/// # let _ = reader;
/// # }
/// ```
pub type EndianRcSlice<Endian> = EndianReader<Endian, Rc<[u8]>>;
/// An atomically reference counted, thread-safe slice of bytes and associated
/// endianity.
///
/// ```
/// # #[cfg(feature = "std")] {
/// use std::sync::Arc;
///
/// let buf = Arc::from(&[1, 2, 3, 4][..]);
/// let reader = gimli::EndianArcSlice::new(buf, gimli::NativeEndian);
/// # let _ = reader;
/// # }
/// ```
pub type EndianArcSlice<Endian> = EndianReader<Endian, Arc<[u8]>>;
/// An easy way to define a custom `Reader` implementation with a reference to a
/// generic buffer of bytes and an associated endianity.
///
/// Note that the whole original buffer is kept alive in memory even if there is
/// only one reader that references only a handful of bytes from that original
/// buffer. That is, `EndianReader` will not do any copying, moving, or
/// compacting in order to free up unused regions of the original buffer. If you
/// require this kind of behavior, it is up to you to implement `Reader`
/// directly by-hand.
///
/// # Example
///
/// Say you have an `mmap`ed file that you want to serve as a `gimli::Reader`.
/// You can wrap that `mmap`ed file up in a `MmapFile` type and use
/// `EndianReader<Rc<MmapFile>>` or `EndianReader<Arc<MmapFile>>` as readers as
/// long as `MmapFile` dereferences to the underlying `[u8]` data.
///
/// ```
/// use std::io;
/// use std::ops::Deref;
/// use std::path::Path;
/// use std::slice;
/// use std::sync::Arc;
///
/// /// A type that represents an `mmap`ed file.
/// #[derive(Debug)]
/// pub struct MmapFile {
/// ptr: *const u8,
/// len: usize,
/// }
///
/// impl MmapFile {
/// pub fn new(path: &Path) -> io::Result<MmapFile> {
/// // Call `mmap` and check for errors and all that...
/// # unimplemented!()
/// }
/// }
///
/// impl Drop for MmapFile {
/// fn drop(&mut self) {
/// // Call `munmap` to clean up after ourselves...
/// # unimplemented!()
/// }
/// }
///
/// // And `MmapFile` can deref to a slice of the `mmap`ed region of memory.
/// impl Deref for MmapFile {
/// type Target = [u8];
/// fn deref(&self) -> &[u8] {
/// unsafe {
/// slice::from_raw_parts(self.ptr, self.len)
/// }
/// }
/// }
///
/// /// A type that represents a shared `mmap`ed file.
/// #[derive(Debug, Clone)]
/// pub struct ArcMmapFile(Arc<MmapFile>);
///
/// // And `ArcMmapFile` can deref to a slice of the `mmap`ed region of memory.
/// impl Deref for ArcMmapFile {
/// type Target = [u8];
/// fn deref(&self) -> &[u8] {
/// &self.0
/// }
/// }
///
/// // These are both valid for any `Rc` or `Arc`.
/// unsafe impl gimli::StableDeref for ArcMmapFile {}
/// unsafe impl gimli::CloneStableDeref for ArcMmapFile {}
///
/// /// A `gimli::Reader` that is backed by an `mmap`ed file!
/// pub type MmapFileReader<Endian> = gimli::EndianReader<Endian, ArcMmapFile>;
/// # fn test(_: &MmapFileReader<gimli::NativeEndian>) { }
/// ```
#[derive(Debug, Clone, Copy, Hash)]
pub struct EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
range: SubRange<T>,
endian: Endian,
}
impl<Endian, T1, T2> PartialEq<EndianReader<Endian, T2>> for EndianReader<Endian, T1>
where
Endian: Endianity,
T1: CloneStableDeref<Target = [u8]> + Debug,
T2: CloneStableDeref<Target = [u8]> + Debug,
{
fn eq(&self, rhs: &EndianReader<Endian, T2>) -> bool {
self.bytes() == rhs.bytes()
}
}
impl<Endian, T> Eq for EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
}
// This is separated out from `EndianReader` so that we can avoid running afoul
// of borrowck. We need to `read_slice(&mut self, ...) -> &[u8]` and then call
// `self.endian.read_whatever` on the result. The problem is that the returned
// slice keeps the `&mut self` borrow active, so we wouldn't be able to access
// `self.endian`. Splitting the sub-range out from the endian lets us work
// around this, making it so that only the `self.range` borrow is held active,
// not all of `self`.
//
// This also serves to encapsulate the unsafe code concerning `CloneStableDeref`.
// The `bytes` member is held so that the bytes live long enough, and the
// `CloneStableDeref` ensures these bytes never move. The `ptr` and `len`
// members point inside `bytes`, and are updated during read operations.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct SubRange<T>
where
T: CloneStableDeref<Target = [u8]> + Debug,
{
bytes: T,
ptr: *const u8,
len: usize,
}
unsafe impl<T> Send for SubRange<T> where T: CloneStableDeref<Target = [u8]> + Debug + Send {}
unsafe impl<T> Sync for SubRange<T> where T: CloneStableDeref<Target = [u8]> + Debug + Sync {}
impl<T> SubRange<T>
where
T: CloneStableDeref<Target = [u8]> + Debug,
{
#[inline]
fn new(bytes: T) -> Self {
let ptr = bytes.as_ptr();
let len = bytes.len();
SubRange { bytes, ptr, len }
}
#[inline]
fn bytes(&self) -> &[u8] {
// Safe because `T` implements `CloneStableDeref`, `bytes` can't be modified,
// and all operations that modify `ptr` and `len` ensure they stay in range.
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
#[inline]
fn len(&self) -> usize {
self.len
}
#[inline]
fn truncate(&mut self, len: usize) {
assert!(len <= self.len);
self.len = len;
}
#[inline]
fn skip(&mut self, len: usize) {
assert!(len <= self.len);
self.ptr = unsafe { self.ptr.add(len) };
self.len -= len;
}
#[inline]
fn read_slice(&mut self, len: usize) -> Option<&[u8]> {
if self.len() < len {
None
} else {
// Same as for `bytes()`.
let bytes = unsafe { slice::from_raw_parts(self.ptr, len) };
self.skip(len);
Some(bytes)
}
}
}
impl<Endian, T> EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
/// Construct a new `EndianReader` with the given bytes.
#[inline]
pub fn new(bytes: T, endian: Endian) -> EndianReader<Endian, T> {
EndianReader {
range: SubRange::new(bytes),
endian,
}
}
/// Return a reference to the raw bytes underlying this reader.
#[inline]
pub fn bytes(&self) -> &[u8] {
self.range.bytes()
}
}
/// # Range Methods
///
/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
/// implement `Index<Range<usize>>` to return a new `EndianReader` the way we
/// would like to. Instead, we abandon fancy indexing operators and have these
/// plain old methods.
impl<Endian, T> EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
/// Take the given `start..end` range of the underlying buffer and return a
/// new `EndianReader`.
///
/// ```
/// # #[cfg(feature = "std")] {
/// use gimli::{EndianReader, LittleEndian};
/// use std::sync::Arc;
///
/// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
/// let reader = EndianReader::new(buf.clone(), LittleEndian);
/// assert_eq!(reader.range(1..3),
/// EndianReader::new(&buf[1..3], LittleEndian));
/// # }
/// ```
///
/// # Panics
///
/// Panics if the range is out of bounds.
pub fn range(&self, idx: Range<usize>) -> EndianReader<Endian, T> {
let mut r = self.clone();
r.range.skip(idx.start);
r.range.truncate(idx.len());
r
}
/// Take the given `start..` range of the underlying buffer and return a new
/// `EndianReader`.
///
/// ```
/// # #[cfg(feature = "std")] {
/// use gimli::{EndianReader, LittleEndian};
/// use std::sync::Arc;
///
/// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
/// let reader = EndianReader::new(buf.clone(), LittleEndian);
/// assert_eq!(reader.range_from(2..),
/// EndianReader::new(&buf[2..], LittleEndian));
/// # }
/// ```
///
/// # Panics
///
/// Panics if the range is out of bounds.
pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianReader<Endian, T> {
let mut r = self.clone();
r.range.skip(idx.start);
r
}
/// Take the given `..end` range of the underlying buffer and return a new
/// `EndianReader`.
///
/// ```
/// # #[cfg(feature = "std")] {
/// use gimli::{EndianReader, LittleEndian};
/// use std::sync::Arc;
///
/// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
/// let reader = EndianReader::new(buf.clone(), LittleEndian);
/// assert_eq!(reader.range_to(..3),
/// EndianReader::new(&buf[..3], LittleEndian));
/// # }
/// ```
///
/// # Panics
///
/// Panics if the range is out of bounds.
pub fn range_to(&self, idx: RangeTo<usize>) -> EndianReader<Endian, T> {
let mut r = self.clone();
r.range.truncate(idx.end);
r
}
}
impl<Endian, T> Index<usize> for EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
type Output = u8;
fn index(&self, idx: usize) -> &Self::Output {
&self.bytes()[idx]
}
}
impl<Endian, T> Index<RangeFrom<usize>> for EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
type Output = [u8];
fn index(&self, idx: RangeFrom<usize>) -> &Self::Output {
&self.bytes()[idx]
}
}
impl<Endian, T> Deref for EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.bytes()
}
}
impl<Endian, T> Reader for EndianReader<Endian, T>
where
Endian: Endianity,
T: CloneStableDeref<Target = [u8]> + Debug,
{
type Endian = Endian;
type Offset = usize;
#[inline]
fn endian(&self) -> Endian {
self.endian
}
#[inline]
fn len(&self) -> usize {
self.range.len()
}
#[inline]
fn empty(&mut self) {
self.range.truncate(0);
}
#[inline]
fn truncate(&mut self, len: usize) -> Result<()> {
if self.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
self.range.truncate(len);
Ok(())
}
}
#[inline]
fn offset_from(&self, base: &EndianReader<Endian, T>) -> usize {
let base_ptr = base.bytes().as_ptr() as *const u8 as usize;
let ptr = self.bytes().as_ptr() as *const u8 as usize;
debug_assert!(base_ptr <= ptr);
debug_assert!(ptr + self.bytes().len() <= base_ptr + base.bytes().len());
ptr - base_ptr
}
#[inline]
fn offset_id(&self) -> ReaderOffsetId {
ReaderOffsetId(self.bytes().as_ptr() as u64)
}
#[inline]
fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
let id = id.0;
let self_id = self.bytes().as_ptr() as u64;
let self_len = self.bytes().len() as u64;
if id >= self_id && id <= self_id + self_len {
Some((id - self_id) as usize)
} else {
None
}
}
#[inline]
fn find(&self, byte: u8) -> Result<usize> {
self.bytes()
.iter()
.position(|x| *x == byte)
.ok_or_else(|| Error::UnexpectedEof(self.offset_id()))
}
#[inline]
fn skip(&mut self, len: usize) -> Result<()> {
if self.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
self.range.skip(len);
Ok(())
}
}
#[inline]
fn split(&mut self, len: usize) -> Result<Self> {
if self.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
let mut r = self.clone();
r.range.truncate(len);
self.range.skip(len);
Ok(r)
}
}
#[inline]
fn to_slice(&self) -> Result<Cow<[u8]>> {
Ok(self.bytes().into())
}
#[inline]
fn to_string(&self) -> Result<Cow<str>> {
match str::from_utf8(self.bytes()) {
Ok(s) => Ok(s.into()),
_ => Err(Error::BadUtf8),
}
}
#[inline]
fn to_string_lossy(&self) -> Result<Cow<str>> {
Ok(String::from_utf8_lossy(self.bytes()))
}
#[inline]
fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
match self.range.read_slice(buf.len()) {
Some(slice) => {
buf.copy_from_slice(slice);
Ok(())
}
None => Err(Error::UnexpectedEof(self.offset_id())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::endianity::NativeEndian;
use crate::read::Reader;
fn native_reader<T: CloneStableDeref<Target = [u8]> + Debug>(
bytes: T,
) -> EndianReader<NativeEndian, T> {
EndianReader::new(bytes, NativeEndian)
}
const BUF: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
#[test]
fn test_reader_split() {
let mut reader = native_reader(BUF);
let left = reader.split(3).unwrap();
assert_eq!(left, native_reader(&BUF[..3]));
assert_eq!(reader, native_reader(&BUF[3..]));
}
#[test]
fn test_reader_split_out_of_bounds() {
let mut reader = native_reader(BUF);
assert!(reader.split(30).is_err());
}
#[test]
fn bytes_and_len_and_range_and_eq() {
let reader = native_reader(BUF);
assert_eq!(reader.len(), BUF.len());
assert_eq!(reader.bytes(), BUF);
assert_eq!(reader, native_reader(BUF));
let range = reader.range(2..8);
let buf_range = &BUF[2..8];
assert_eq!(range.len(), buf_range.len());
assert_eq!(range.bytes(), buf_range);
assert_ne!(range, native_reader(BUF));
assert_eq!(range, native_reader(buf_range));
let range_from = range.range_from(1..);
let buf_range_from = &buf_range[1..];
assert_eq!(range_from.len(), buf_range_from.len());
assert_eq!(range_from.bytes(), buf_range_from);
assert_ne!(range_from, native_reader(BUF));
assert_eq!(range_from, native_reader(buf_range_from));
let range_to = range_from.range_to(..4);
let buf_range_to = &buf_range_from[..4];
assert_eq!(range_to.len(), buf_range_to.len());
assert_eq!(range_to.bytes(), buf_range_to);
assert_ne!(range_to, native_reader(BUF));
assert_eq!(range_to, native_reader(buf_range_to));
}
#[test]
fn find() {
let mut reader = native_reader(BUF);
reader.skip(2).unwrap();
assert_eq!(
reader.find(5),
Ok(BUF[2..].iter().position(|x| *x == 5).unwrap())
);
}
#[test]
fn indexing() {
let mut reader = native_reader(BUF);
reader.skip(2).unwrap();
assert_eq!(reader[0], BUF[2]);
}
#[test]
#[should_panic]
fn indexing_out_of_bounds() {
let mut reader = native_reader(BUF);
reader.skip(2).unwrap();
let _ = reader[900];
}
#[test]
fn endian() {
let reader = native_reader(BUF);
assert_eq!(reader.endian(), NativeEndian);
}
#[test]
fn empty() {
let mut reader = native_reader(BUF);
assert!(!reader.is_empty());
reader.empty();
assert!(reader.is_empty());
assert!(reader.bytes().is_empty());
}
#[test]
fn truncate() {
let reader = native_reader(BUF);
let mut reader = reader.range(2..8);
reader.truncate(2).unwrap();
assert_eq!(reader.bytes(), &BUF[2..4]);
}
#[test]
fn offset_from() {
let reader = native_reader(BUF);
let sub = reader.range(2..8);
assert_eq!(sub.offset_from(&reader), 2);
}
#[test]
fn skip() {
let mut reader = native_reader(BUF);
reader.skip(2).unwrap();
assert_eq!(reader.bytes(), &BUF[2..]);
}
#[test]
fn to_slice() {
assert_eq!(
native_reader(BUF).range(2..5).to_slice(),
Ok(Cow::from(&BUF[2..5]))
);
}
#[test]
fn to_string_ok() {
let buf = b"hello, world!";
let reader = native_reader(&buf[..]);
let reader = reader.range_from(7..);
assert_eq!(reader.to_string(), Ok(Cow::from("world!")));
}
// The rocket emoji (🚀 = [0xf0, 0x9f, 0x9a, 0x80]) but rotated left by one
// to make it invalid UTF-8.
const BAD_UTF8: &[u8] = &[0x9f, 0x9a, 0x80, 0xf0];
#[test]
fn to_string_err() {
let reader = native_reader(BAD_UTF8);
assert!(reader.to_string().is_err());
}
#[test]
fn to_string_lossy() {
let reader = native_reader(BAD_UTF8);
assert_eq!(reader.to_string_lossy(), Ok(Cow::from("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>")));
}
#[test]
fn read_u8_array() {
let mut reader = native_reader(BAD_UTF8);
reader.skip(1).unwrap();
let arr: [u8; 2] = reader.read_u8_array().unwrap();
assert_eq!(arr, &BAD_UTF8[1..3]);
assert_eq!(reader.bytes(), &BAD_UTF8[3..]);
}
}

360
vendor/gimli/src/read/endian_slice.rs vendored Normal file
View File

@ -0,0 +1,360 @@
//! Working with byte slices that have an associated endianity.
#[cfg(feature = "read")]
use alloc::borrow::Cow;
#[cfg(feature = "read")]
use alloc::string::String;
use core::fmt;
use core::ops::{Deref, Range, RangeFrom, RangeTo};
use core::str;
use crate::endianity::Endianity;
use crate::read::{Error, Reader, ReaderOffsetId, Result};
/// A `&[u8]` slice with endianity metadata.
///
/// This implements the `Reader` trait, which is used for all reading of DWARF sections.
#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EndianSlice<'input, Endian>
where
Endian: Endianity,
{
slice: &'input [u8],
endian: Endian,
}
impl<'input, Endian> EndianSlice<'input, Endian>
where
Endian: Endianity,
{
/// Construct a new `EndianSlice` with the given slice and endianity.
#[inline]
pub fn new(slice: &'input [u8], endian: Endian) -> EndianSlice<'input, Endian> {
EndianSlice { slice, endian }
}
/// Return a reference to the raw slice.
#[inline]
#[doc(hidden)]
#[deprecated(note = "Method renamed to EndianSlice::slice; use that instead.")]
pub fn buf(&self) -> &'input [u8] {
self.slice
}
/// Return a reference to the raw slice.
#[inline]
pub fn slice(&self) -> &'input [u8] {
self.slice
}
/// Split the slice in two at the given index, resulting in the tuple where
/// the first item has range [0, idx), and the second has range [idx,
/// len). Panics if the index is out of bounds.
#[inline]
pub fn split_at(
&self,
idx: usize,
) -> (EndianSlice<'input, Endian>, EndianSlice<'input, Endian>) {
(self.range_to(..idx), self.range_from(idx..))
}
/// Find the first occurrence of a byte in the slice, and return its index.
#[inline]
pub fn find(&self, byte: u8) -> Option<usize> {
self.slice.iter().position(|ch| *ch == byte)
}
/// Return the offset of the start of the slice relative to the start
/// of the given slice.
#[inline]
pub fn offset_from(&self, base: EndianSlice<'input, Endian>) -> usize {
let base_ptr = base.slice.as_ptr() as *const u8 as usize;
let ptr = self.slice.as_ptr() as *const u8 as usize;
debug_assert!(base_ptr <= ptr);
debug_assert!(ptr + self.slice.len() <= base_ptr + base.slice.len());
ptr - base_ptr
}
/// Converts the slice to a string using `str::from_utf8`.
///
/// Returns an error if the slice contains invalid characters.
#[inline]
pub fn to_string(&self) -> Result<&'input str> {
str::from_utf8(self.slice).map_err(|_| Error::BadUtf8)
}
/// Converts the slice to a string, including invalid characters,
/// using `String::from_utf8_lossy`.
#[cfg(feature = "read")]
#[inline]
pub fn to_string_lossy(&self) -> Cow<'input, str> {
String::from_utf8_lossy(self.slice)
}
#[inline]
fn read_slice(&mut self, len: usize) -> Result<&'input [u8]> {
if self.slice.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
let val = &self.slice[..len];
self.slice = &self.slice[len..];
Ok(val)
}
}
}
/// # Range Methods
///
/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
/// implement `Index<Range<usize>>` to return a new `EndianSlice` the way we would
/// like to. Instead, we abandon fancy indexing operators and have these plain
/// old methods.
impl<'input, Endian> EndianSlice<'input, Endian>
where
Endian: Endianity,
{
/// Take the given `start..end` range of the underlying slice and return a
/// new `EndianSlice`.
///
/// ```
/// use gimli::{EndianSlice, LittleEndian};
///
/// let slice = &[0x01, 0x02, 0x03, 0x04];
/// let endian_slice = EndianSlice::new(slice, LittleEndian);
/// assert_eq!(endian_slice.range(1..3),
/// EndianSlice::new(&slice[1..3], LittleEndian));
/// ```
pub fn range(&self, idx: Range<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
/// Take the given `start..` range of the underlying slice and return a new
/// `EndianSlice`.
///
/// ```
/// use gimli::{EndianSlice, LittleEndian};
///
/// let slice = &[0x01, 0x02, 0x03, 0x04];
/// let endian_slice = EndianSlice::new(slice, LittleEndian);
/// assert_eq!(endian_slice.range_from(2..),
/// EndianSlice::new(&slice[2..], LittleEndian));
/// ```
pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
/// Take the given `..end` range of the underlying slice and return a new
/// `EndianSlice`.
///
/// ```
/// use gimli::{EndianSlice, LittleEndian};
///
/// let slice = &[0x01, 0x02, 0x03, 0x04];
/// let endian_slice = EndianSlice::new(slice, LittleEndian);
/// assert_eq!(endian_slice.range_to(..3),
/// EndianSlice::new(&slice[..3], LittleEndian));
/// ```
pub fn range_to(&self, idx: RangeTo<usize>) -> EndianSlice<'input, Endian> {
EndianSlice {
slice: &self.slice[idx],
endian: self.endian,
}
}
}
impl<'input, Endian> Deref for EndianSlice<'input, Endian>
where
Endian: Endianity,
{
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.slice
}
}
impl<'input, Endian: Endianity> fmt::Debug for EndianSlice<'input, Endian> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
fmt.debug_tuple("EndianSlice")
.field(&self.endian)
.field(&DebugBytes(self.slice))
.finish()
}
}
struct DebugBytes<'input>(&'input [u8]);
impl<'input> core::fmt::Debug for DebugBytes<'input> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> core::result::Result<(), fmt::Error> {
let mut list = fmt.debug_list();
list.entries(self.0.iter().take(8).copied().map(DebugByte));
if self.0.len() > 8 {
list.entry(&DebugLen(self.0.len()));
}
list.finish()
}
}
struct DebugByte(u8);
impl fmt::Debug for DebugByte {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "0x{:02x}", self.0)
}
}
struct DebugLen(usize);
impl fmt::Debug for DebugLen {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "...; {}", self.0)
}
}
impl<'input, Endian> Reader for EndianSlice<'input, Endian>
where
Endian: Endianity,
{
type Endian = Endian;
type Offset = usize;
#[inline]
fn endian(&self) -> Endian {
self.endian
}
#[inline]
fn len(&self) -> usize {
self.slice.len()
}
#[inline]
fn is_empty(&self) -> bool {
self.slice.is_empty()
}
#[inline]
fn empty(&mut self) {
self.slice = &[];
}
#[inline]
fn truncate(&mut self, len: usize) -> Result<()> {
if self.slice.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
self.slice = &self.slice[..len];
Ok(())
}
}
#[inline]
fn offset_from(&self, base: &Self) -> usize {
self.offset_from(*base)
}
#[inline]
fn offset_id(&self) -> ReaderOffsetId {
ReaderOffsetId(self.slice.as_ptr() as u64)
}
#[inline]
fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
let id = id.0;
let self_id = self.slice.as_ptr() as u64;
let self_len = self.slice.len() as u64;
if id >= self_id && id <= self_id + self_len {
Some((id - self_id) as usize)
} else {
None
}
}
#[inline]
fn find(&self, byte: u8) -> Result<usize> {
self.find(byte)
.ok_or_else(|| Error::UnexpectedEof(self.offset_id()))
}
#[inline]
fn skip(&mut self, len: usize) -> Result<()> {
if self.slice.len() < len {
Err(Error::UnexpectedEof(self.offset_id()))
} else {
self.slice = &self.slice[len..];
Ok(())
}
}
#[inline]
fn split(&mut self, len: usize) -> Result<Self> {
let slice = self.read_slice(len)?;
Ok(EndianSlice::new(slice, self.endian))
}
#[cfg(not(feature = "read"))]
fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
super::reader::seal_if_no_alloc::Sealed
}
#[cfg(feature = "read")]
#[inline]
fn to_slice(&self) -> Result<Cow<[u8]>> {
Ok(self.slice.into())
}
#[cfg(feature = "read")]
#[inline]
fn to_string(&self) -> Result<Cow<str>> {
match str::from_utf8(self.slice) {
Ok(s) => Ok(s.into()),
_ => Err(Error::BadUtf8),
}
}
#[cfg(feature = "read")]
#[inline]
fn to_string_lossy(&self) -> Result<Cow<str>> {
Ok(String::from_utf8_lossy(self.slice))
}
#[inline]
fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
let slice = self.read_slice(buf.len())?;
buf.copy_from_slice(slice);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::endianity::NativeEndian;
#[test]
fn test_endian_slice_split_at() {
let endian = NativeEndian;
let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
let eb = EndianSlice::new(slice, endian);
assert_eq!(
eb.split_at(3),
(
EndianSlice::new(&slice[..3], endian),
EndianSlice::new(&slice[3..], endian)
)
);
}
#[test]
#[should_panic]
fn test_endian_slice_split_at_out_of_bounds() {
let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
let eb = EndianSlice::new(slice, NativeEndian);
eb.split_at(30);
}
}

535
vendor/gimli/src/read/index.rs vendored Normal file
View File

@ -0,0 +1,535 @@
use core::slice;
use crate::common::SectionId;
use crate::constants;
use crate::endianity::Endianity;
use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section};
/// The data in the `.debug_cu_index` section of a `.dwp` file.
///
/// This section contains the compilation unit index.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugCuIndex<R> {
section: R,
}
impl<'input, Endian> DebugCuIndex<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index`
/// section.
pub fn new(section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(section, endian))
}
}
impl<R> Section<R> for DebugCuIndex<R> {
fn id() -> SectionId {
SectionId::DebugCuIndex
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugCuIndex<R> {
fn from(section: R) -> Self {
DebugCuIndex { section }
}
}
impl<R: Reader> DebugCuIndex<R> {
/// Parse the index header.
pub fn index(self) -> Result<UnitIndex<R>> {
UnitIndex::parse(self.section)
}
}
/// The data in the `.debug_tu_index` section of a `.dwp` file.
///
/// This section contains the type unit index.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugTuIndex<R> {
section: R,
}
impl<'input, Endian> DebugTuIndex<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index`
/// section.
pub fn new(section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(section, endian))
}
}
impl<R> Section<R> for DebugTuIndex<R> {
fn id() -> SectionId {
SectionId::DebugTuIndex
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugTuIndex<R> {
fn from(section: R) -> Self {
DebugTuIndex { section }
}
}
impl<R: Reader> DebugTuIndex<R> {
/// Parse the index header.
pub fn index(self) -> Result<UnitIndex<R>> {
UnitIndex::parse(self.section)
}
}
const SECTION_COUNT_MAX: u8 = 8;
/// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`.
#[derive(Debug, Clone)]
pub struct UnitIndex<R: Reader> {
version: u16,
section_count: u32,
unit_count: u32,
slot_count: u32,
hash_ids: R,
hash_rows: R,
// Only `section_count` values are valid.
sections: [SectionId; SECTION_COUNT_MAX as usize],
offsets: R,
sizes: R,
}
impl<R: Reader> UnitIndex<R> {
fn parse(mut input: R) -> Result<UnitIndex<R>> {
if input.is_empty() {
return Ok(UnitIndex {
version: 5,
section_count: 0,
unit_count: 0,
slot_count: 0,
hash_ids: input.clone(),
hash_rows: input.clone(),
sections: [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize],
offsets: input.clone(),
sizes: input.clone(),
});
}
// GNU split-dwarf extension to DWARF 4 uses a 32-bit version,
// but DWARF 5 uses a 16-bit version followed by 16-bit padding.
let mut original_input = input.clone();
let version;
if input.read_u32()? == 2 {
version = 2
} else {
version = original_input.read_u16()?;
if version != 5 {
return Err(Error::UnknownVersion(version.into()));
}
}
let section_count = input.read_u32()?;
let unit_count = input.read_u32()?;
let slot_count = input.read_u32()?;
if slot_count == 0 || slot_count & (slot_count - 1) != 0 || slot_count <= unit_count {
return Err(Error::InvalidIndexSlotCount);
}
let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?;
let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?;
let mut sections = [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize];
if section_count > SECTION_COUNT_MAX.into() {
return Err(Error::InvalidIndexSectionCount);
}
for i in 0..section_count {
let section = input.read_u32()?;
sections[i as usize] = if version == 2 {
match constants::DwSectV2(section) {
constants::DW_SECT_V2_INFO => SectionId::DebugInfo,
constants::DW_SECT_V2_TYPES => SectionId::DebugTypes,
constants::DW_SECT_V2_ABBREV => SectionId::DebugAbbrev,
constants::DW_SECT_V2_LINE => SectionId::DebugLine,
constants::DW_SECT_V2_LOC => SectionId::DebugLoc,
constants::DW_SECT_V2_STR_OFFSETS => SectionId::DebugStrOffsets,
constants::DW_SECT_V2_MACINFO => SectionId::DebugMacinfo,
constants::DW_SECT_V2_MACRO => SectionId::DebugMacro,
_ => return Err(Error::UnknownIndexSection),
}
} else {
match constants::DwSect(section) {
constants::DW_SECT_INFO => SectionId::DebugInfo,
constants::DW_SECT_ABBREV => SectionId::DebugAbbrev,
constants::DW_SECT_LINE => SectionId::DebugLine,
constants::DW_SECT_LOCLISTS => SectionId::DebugLocLists,
constants::DW_SECT_STR_OFFSETS => SectionId::DebugStrOffsets,
constants::DW_SECT_MACRO => SectionId::DebugMacro,
constants::DW_SECT_RNGLISTS => SectionId::DebugRngLists,
_ => return Err(Error::UnknownIndexSection),
}
};
}
let offsets = input.split(R::Offset::from_u64(
u64::from(unit_count) * u64::from(section_count) * 4,
)?)?;
let sizes = input.split(R::Offset::from_u64(
u64::from(unit_count) * u64::from(section_count) * 4,
)?)?;
Ok(UnitIndex {
version,
section_count,
unit_count,
slot_count,
hash_ids,
hash_rows,
sections,
offsets,
sizes,
})
}
/// Find `id` in the index hash table, and return the row index.
///
/// `id` may be a compilation unit ID if this index is from `.debug_cu_index`,
/// or a type signature if this index is from `.debug_tu_index`.
pub fn find(&self, id: u64) -> Option<u32> {
if self.slot_count == 0 {
return None;
}
let mask = u64::from(self.slot_count - 1);
let mut hash1 = id & mask;
let hash2 = ((id >> 32) & mask) | 1;
for _ in 0..self.slot_count {
// The length of these arrays was validated in `UnitIndex::parse`.
let mut hash_ids = self.hash_ids.clone();
hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?;
let hash_id = hash_ids.read_u64().ok()?;
if hash_id == id {
let mut hash_rows = self.hash_rows.clone();
hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?;
let hash_row = hash_rows.read_u32().ok()?;
return Some(hash_row);
}
if hash_id == 0 {
return None;
}
hash1 = (hash1 + hash2) & mask;
}
None
}
/// Return the section offsets and sizes for the given row index.
pub fn sections(&self, mut row: u32) -> Result<UnitIndexSectionIterator<R>> {
if row == 0 {
return Err(Error::InvalidIndexRow);
}
row -= 1;
if row >= self.unit_count {
return Err(Error::InvalidIndexRow);
}
let mut offsets = self.offsets.clone();
offsets.skip(R::Offset::from_u64(
u64::from(row) * u64::from(self.section_count) * 4,
)?)?;
let mut sizes = self.sizes.clone();
sizes.skip(R::Offset::from_u64(
u64::from(row) * u64::from(self.section_count) * 4,
)?)?;
Ok(UnitIndexSectionIterator {
sections: self.sections[..self.section_count as usize].iter(),
offsets,
sizes,
})
}
/// Return the version.
pub fn version(&self) -> u16 {
self.version
}
/// Return the number of sections.
pub fn section_count(&self) -> u32 {
self.section_count
}
/// Return the number of units.
pub fn unit_count(&self) -> u32 {
self.unit_count
}
/// Return the number of slots.
pub fn slot_count(&self) -> u32 {
self.slot_count
}
}
/// An iterator over the section offsets and sizes for a row in a `UnitIndex`.
#[derive(Debug, Clone)]
pub struct UnitIndexSectionIterator<'index, R: Reader> {
sections: slice::Iter<'index, SectionId>,
offsets: R,
sizes: R,
}
impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> {
type Item = UnitIndexSection;
fn next(&mut self) -> Option<UnitIndexSection> {
let section = *self.sections.next()?;
// The length of these arrays was validated in `UnitIndex::parse`.
let offset = self.offsets.read_u32().ok()?;
let size = self.sizes.read_u32().ok()?;
Some(UnitIndexSection {
section,
offset,
size,
})
}
}
/// Information about a unit's contribution to a section in a `.dwp` file.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct UnitIndexSection {
/// The section kind.
pub section: SectionId,
/// The base offset of the unit's contribution to the section.
pub offset: u32,
/// The size of the unit's contribution to the section.
pub size: u32,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::endianity::BigEndian;
use test_assembler::{Endian, Section};
#[test]
fn test_empty() {
let buf = EndianSlice::new(&[], BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert!(index.find(0).is_none());
}
#[test]
fn test_version_2() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D32(2).D32(0).D32(0).D32(1)
// Slots.
.D64(0).D32(0);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.version, 2);
}
#[test]
fn test_version_5() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D16(5).D16(0).D32(0).D32(0).D32(1)
// Slots.
.D64(0).D32(0);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.version, 5);
}
#[test]
fn test_version_5_invalid() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D32(5).D32(0).D32(0).D32(1)
// Slots.
.D64(0).D32(0);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
assert!(UnitIndex::parse(buf).is_err());
}
#[test]
fn test_version_2_sections() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D32(2).D32(8).D32(1).D32(2)
// Slots.
.D64(0).D64(0).D32(0).D32(0)
// Sections.
.D32(constants::DW_SECT_V2_INFO.0)
.D32(constants::DW_SECT_V2_TYPES.0)
.D32(constants::DW_SECT_V2_ABBREV.0)
.D32(constants::DW_SECT_V2_LINE.0)
.D32(constants::DW_SECT_V2_LOC.0)
.D32(constants::DW_SECT_V2_STR_OFFSETS.0)
.D32(constants::DW_SECT_V2_MACINFO.0)
.D32(constants::DW_SECT_V2_MACRO.0)
// Offsets.
.D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18)
// Sizes.
.D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.section_count, 8);
assert_eq!(
index.sections,
[
SectionId::DebugInfo,
SectionId::DebugTypes,
SectionId::DebugAbbrev,
SectionId::DebugLine,
SectionId::DebugLoc,
SectionId::DebugStrOffsets,
SectionId::DebugMacinfo,
SectionId::DebugMacro,
]
);
#[rustfmt::skip]
let expect = [
UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: SectionId::DebugTypes, offset: 12, size: 22 },
UnitIndexSection { section: SectionId::DebugAbbrev, offset: 13, size: 23 },
UnitIndexSection { section: SectionId::DebugLine, offset: 14, size: 24 },
UnitIndexSection { section: SectionId::DebugLoc, offset: 15, size: 25 },
UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 16, size: 26 },
UnitIndexSection { section: SectionId::DebugMacinfo, offset: 17, size: 27 },
UnitIndexSection { section: SectionId::DebugMacro, offset: 18, size: 28 },
];
let mut sections = index.sections(1).unwrap();
for section in &expect {
assert_eq!(*section, sections.next().unwrap());
}
assert!(sections.next().is_none());
}
#[test]
fn test_version_5_sections() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D16(5).D16(0).D32(7).D32(1).D32(2)
// Slots.
.D64(0).D64(0).D32(0).D32(0)
// Sections.
.D32(constants::DW_SECT_INFO.0)
.D32(constants::DW_SECT_ABBREV.0)
.D32(constants::DW_SECT_LINE.0)
.D32(constants::DW_SECT_LOCLISTS.0)
.D32(constants::DW_SECT_STR_OFFSETS.0)
.D32(constants::DW_SECT_MACRO.0)
.D32(constants::DW_SECT_RNGLISTS.0)
// Offsets.
.D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17)
// Sizes.
.D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.section_count, 7);
assert_eq!(
index.sections[..7],
[
SectionId::DebugInfo,
SectionId::DebugAbbrev,
SectionId::DebugLine,
SectionId::DebugLocLists,
SectionId::DebugStrOffsets,
SectionId::DebugMacro,
SectionId::DebugRngLists,
]
);
#[rustfmt::skip]
let expect = [
UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
UnitIndexSection { section: SectionId::DebugAbbrev, offset: 12, size: 22 },
UnitIndexSection { section: SectionId::DebugLine, offset: 13, size: 23 },
UnitIndexSection { section: SectionId::DebugLocLists, offset: 14, size: 24 },
UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 15, size: 25 },
UnitIndexSection { section: SectionId::DebugMacro, offset: 16, size: 26 },
UnitIndexSection { section: SectionId::DebugRngLists, offset: 17, size: 27 },
];
let mut sections = index.sections(1).unwrap();
for section in &expect {
assert_eq!(*section, sections.next().unwrap());
}
assert!(sections.next().is_none());
assert!(index.sections(0).is_err());
assert!(index.sections(2).is_err());
}
#[test]
fn test_hash() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D16(5).D16(0).D32(2).D32(3).D32(4)
// Slots.
.D64(0xffff_fff2_ffff_fff1)
.D64(0xffff_fff0_ffff_fff1)
.D64(0xffff_fff1_ffff_fff1)
.D64(0)
.D32(3).D32(1).D32(2).D32(0)
// Sections.
.D32(constants::DW_SECT_INFO.0)
.D32(constants::DW_SECT_ABBREV.0)
// Offsets.
.D32(0).D32(0).D32(0).D32(0).D32(0).D32(0)
// Sizes.
.D32(0).D32(0).D32(0).D32(0).D32(0).D32(0);
let buf = section.get_contents().unwrap();
let buf = EndianSlice::new(&buf, BigEndian);
let index = UnitIndex::parse(buf).unwrap();
assert_eq!(index.version(), 5);
assert_eq!(index.slot_count(), 4);
assert_eq!(index.unit_count(), 3);
assert_eq!(index.section_count(), 2);
assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1));
assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2));
assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3));
assert_eq!(index.find(0xffff_fff3_ffff_fff1), None);
}
#[test]
fn test_cu_index() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D16(5).D16(0).D32(0).D32(0).D32(1)
// Slots.
.D64(0).D32(0);
let buf = section.get_contents().unwrap();
let cu_index = DebugCuIndex::new(&buf, BigEndian);
let index = cu_index.index().unwrap();
assert_eq!(index.version, 5);
}
#[test]
fn test_tu_index() {
#[rustfmt::skip]
let section = Section::with_endian(Endian::Big)
// Header.
.D16(5).D16(0).D32(0).D32(0).D32(1)
// Slots.
.D64(0).D32(0);
let buf = section.get_contents().unwrap();
let tu_index = DebugTuIndex::new(&buf, BigEndian);
let index = tu_index.index().unwrap();
assert_eq!(index.version, 5);
}
}

3130
vendor/gimli/src/read/line.rs vendored Normal file

File diff suppressed because it is too large Load Diff

68
vendor/gimli/src/read/lists.rs vendored Normal file
View File

@ -0,0 +1,68 @@
use crate::common::{Encoding, Format};
use crate::read::{Error, Reader, Result};
#[derive(Debug, Clone, Copy)]
pub(crate) struct ListsHeader {
encoding: Encoding,
#[allow(dead_code)]
offset_entry_count: u32,
}
impl Default for ListsHeader {
fn default() -> Self {
ListsHeader {
encoding: Encoding {
format: Format::Dwarf32,
version: 5,
address_size: 0,
},
offset_entry_count: 0,
}
}
}
impl ListsHeader {
/// Return the serialized size of the table header.
#[allow(dead_code)]
#[inline]
fn size(self) -> u8 {
// initial_length + version + address_size + segment_selector_size + offset_entry_count
ListsHeader::size_for_encoding(self.encoding)
}
/// Return the serialized size of the table header.
#[inline]
pub(crate) fn size_for_encoding(encoding: Encoding) -> u8 {
// initial_length + version + address_size + segment_selector_size + offset_entry_count
encoding.format.initial_length_size() + 2 + 1 + 1 + 4
}
}
// TODO: add an iterator over headers in the appropriate sections section
#[allow(dead_code)]
fn parse_header<R: Reader>(input: &mut R) -> Result<ListsHeader> {
let (length, format) = input.read_initial_length()?;
input.truncate(length)?;
let version = input.read_u16()?;
if version != 5 {
return Err(Error::UnknownVersion(u64::from(version)));
}
let address_size = input.read_u8()?;
let segment_selector_size = input.read_u8()?;
if segment_selector_size != 0 {
return Err(Error::UnsupportedSegmentSize);
}
let offset_entry_count = input.read_u32()?;
let encoding = Encoding {
format,
version,
address_size,
};
Ok(ListsHeader {
encoding,
offset_entry_count,
})
}

1627
vendor/gimli/src/read/loclists.rs vendored Normal file

File diff suppressed because it is too large Load Diff

202
vendor/gimli/src/read/lookup.rs vendored Normal file
View File

@ -0,0 +1,202 @@
use core::marker::PhantomData;
use crate::common::{DebugInfoOffset, Format};
use crate::read::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset};
// The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have
// similar structures. They consist of a header with metadata and an offset into the
// .debug_info section for the entire compilation unit, and a series
// of following entries that list addresses (for .debug_aranges) or names
// (for .debug_pubnames and .debug_pubtypes) that are covered.
//
// Because these three tables all have similar structures, we abstract out some of
// the parsing mechanics.
pub trait LookupParser<R: Reader> {
/// The type of the produced header.
type Header;
/// The type of the produced entry.
type Entry;
/// Parse a header from `input`. Returns a tuple of `input` sliced to contain just the entries
/// corresponding to this header (without the header itself), and the parsed representation of
/// the header itself.
fn parse_header(input: &mut R) -> Result<(R, Self::Header)>;
/// Parse a single entry from `input`. Returns either a parsed representation of the entry
/// or None if `input` is exhausted.
fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>>;
}
#[derive(Clone, Debug)]
pub struct DebugLookup<R, Parser>
where
R: Reader,
Parser: LookupParser<R>,
{
input_buffer: R,
phantom: PhantomData<Parser>,
}
impl<R, Parser> From<R> for DebugLookup<R, Parser>
where
R: Reader,
Parser: LookupParser<R>,
{
fn from(input_buffer: R) -> Self {
DebugLookup {
input_buffer,
phantom: PhantomData,
}
}
}
impl<R, Parser> DebugLookup<R, Parser>
where
R: Reader,
Parser: LookupParser<R>,
{
pub fn items(&self) -> LookupEntryIter<R, Parser> {
LookupEntryIter {
current_set: None,
remaining_input: self.input_buffer.clone(),
}
}
pub fn reader(&self) -> &R {
&self.input_buffer
}
}
#[derive(Clone, Debug)]
pub struct LookupEntryIter<R, Parser>
where
R: Reader,
Parser: LookupParser<R>,
{
current_set: Option<(R, Parser::Header)>, // Only none at the very beginning and end.
remaining_input: R,
}
impl<R, Parser> LookupEntryIter<R, Parser>
where
R: Reader,
Parser: LookupParser<R>,
{
/// Advance the iterator and return the next entry.
///
/// Returns the newly parsed entry as `Ok(Some(Parser::Entry))`. Returns
/// `Ok(None)` when iteration is complete and all entries have already been
/// parsed and yielded. If an error occurs while parsing the next entry,
/// then this error is returned as `Err(e)`, and all subsequent calls return
/// `Ok(None)`.
///
/// Can be [used with `FallibleIterator`](./index.html#using-with-fallibleiterator).
pub fn next(&mut self) -> Result<Option<Parser::Entry>> {
loop {
if let Some((ref mut input, ref header)) = self.current_set {
if !input.is_empty() {
match Parser::parse_entry(input, header) {
Ok(Some(entry)) => return Ok(Some(entry)),
Ok(None) => {}
Err(e) => {
input.empty();
self.remaining_input.empty();
return Err(e);
}
}
}
}
if self.remaining_input.is_empty() {
self.current_set = None;
return Ok(None);
}
match Parser::parse_header(&mut self.remaining_input) {
Ok(set) => {
self.current_set = Some(set);
}
Err(e) => {
self.current_set = None;
self.remaining_input.empty();
return Err(e);
}
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PubStuffHeader<T = usize> {
format: Format,
length: T,
version: u16,
unit_offset: DebugInfoOffset<T>,
unit_length: T,
}
pub trait PubStuffEntry<R: Reader> {
fn new(
die_offset: UnitOffset<R::Offset>,
name: R,
unit_header_offset: DebugInfoOffset<R::Offset>,
) -> Self;
}
#[derive(Clone, Debug)]
pub struct PubStuffParser<R, Entry>
where
R: Reader,
Entry: PubStuffEntry<R>,
{
// This struct is never instantiated.
phantom: PhantomData<(R, Entry)>,
}
impl<R, Entry> LookupParser<R> for PubStuffParser<R, Entry>
where
R: Reader,
Entry: PubStuffEntry<R>,
{
type Header = PubStuffHeader<R::Offset>;
type Entry = Entry;
/// Parse an pubthings set header. Returns a tuple of the
/// pubthings to be parsed for this set, and the newly created PubThingHeader struct.
fn parse_header(input: &mut R) -> Result<(R, Self::Header)> {
let (length, format) = input.read_initial_length()?;
let mut rest = input.split(length)?;
let version = rest.read_u16()?;
if version != 2 {
return Err(Error::UnknownVersion(u64::from(version)));
}
let unit_offset = parse_debug_info_offset(&mut rest, format)?;
let unit_length = rest.read_length(format)?;
let header = PubStuffHeader {
format,
length,
version,
unit_offset,
unit_length,
};
Ok((rest, header))
}
/// Parse a single pubthing. Return `None` for the null pubthing, `Some` for an actual pubthing.
fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>> {
let offset = input.read_offset(header.format)?;
if offset.into_u64() == 0 {
input.empty();
Ok(None)
} else {
let name = input.read_null_terminated_slice()?;
Ok(Some(Self::Entry::new(
UnitOffset(offset),
name,
header.unit_offset,
)))
}
}
}

827
vendor/gimli/src/read/mod.rs vendored Normal file
View File

@ -0,0 +1,827 @@
//! Read DWARF debugging information.
//!
//! * [Example Usage](#example-usage)
//! * [API Structure](#api-structure)
//! * [Using with `FallibleIterator`](#using-with-fallibleiterator)
//!
//! ## Example Usage
//!
//! Print out all of the functions in the debuggee program:
//!
//! ```rust,no_run
//! # fn example() -> Result<(), gimli::Error> {
//! # type R = gimli::EndianSlice<'static, gimli::LittleEndian>;
//! # let get_file_section_reader = |name| -> Result<R, gimli::Error> { unimplemented!() };
//! # let get_sup_file_section_reader = |name| -> Result<R, gimli::Error> { unimplemented!() };
//! // Read the DWARF sections with whatever object loader you're using.
//! // These closures should return a `Reader` instance (e.g. `EndianSlice`).
//! let loader = |section: gimli::SectionId| { get_file_section_reader(section.name()) };
//! let sup_loader = |section: gimli::SectionId| { get_sup_file_section_reader(section.name()) };
//! let mut dwarf = gimli::Dwarf::load(loader)?;
//! dwarf.load_sup(sup_loader)?;
//!
//! // Iterate over all compilation units.
//! let mut iter = dwarf.units();
//! while let Some(header) = iter.next()? {
//! // Parse the abbreviations and other information for this compilation unit.
//! let unit = dwarf.unit(header)?;
//!
//! // Iterate over all of this compilation unit's entries.
//! let mut entries = unit.entries();
//! while let Some((_, entry)) = entries.next_dfs()? {
//! // If we find an entry for a function, print it.
//! if entry.tag() == gimli::DW_TAG_subprogram {
//! println!("Found a function: {:?}", entry);
//! }
//! }
//! }
//! # unreachable!()
//! # }
//! ```
//!
//! Full example programs:
//!
//! * [A simple parser](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/simple.rs)
//!
//! * [A `dwarfdump`
//! clone](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarfdump.rs)
//!
//! * [An `addr2line` clone](https://github.com/gimli-rs/addr2line)
//!
//! * [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into
//! code generation by making debugging information readable
//!
//! * [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the
//! compilers used to create each compilation unit within a shared library or
//! executable (via `DW_AT_producer`)
//!
//! * [`dwarf-validate`](https://github.com/gimli-rs/gimli/blob/master/crates/examples/src/bin/dwarf-validate.rs),
//! a program to validate the integrity of some DWARF and its references
//! between sections and compilation units.
//!
//! ## API Structure
//!
//! * Basic familiarity with DWARF is assumed.
//!
//! * The [`Dwarf`](./struct.Dwarf.html) type contains the commonly used DWARF
//! sections. It has methods that simplify access to debugging data that spans
//! multiple sections. Use of this type is optional, but recommended.
//!
//! * Each section gets its own type. Consider these types the entry points to
//! the library:
//!
//! * [`DebugAbbrev`](./struct.DebugAbbrev.html): The `.debug_abbrev` section.
//!
//! * [`DebugAddr`](./struct.DebugAddr.html): The `.debug_addr` section.
//!
//! * [`DebugAranges`](./struct.DebugAranges.html): The `.debug_aranges`
//! section.
//!
//! * [`DebugFrame`](./struct.DebugFrame.html): The `.debug_frame` section.
//!
//! * [`DebugInfo`](./struct.DebugInfo.html): The `.debug_info` section.
//!
//! * [`DebugLine`](./struct.DebugLine.html): The `.debug_line` section.
//!
//! * [`DebugLineStr`](./struct.DebugLineStr.html): The `.debug_line_str` section.
//!
//! * [`DebugLoc`](./struct.DebugLoc.html): The `.debug_loc` section.
//!
//! * [`DebugLocLists`](./struct.DebugLocLists.html): The `.debug_loclists` section.
//!
//! * [`DebugPubNames`](./struct.DebugPubNames.html): The `.debug_pubnames`
//! section.
//!
//! * [`DebugPubTypes`](./struct.DebugPubTypes.html): The `.debug_pubtypes`
//! section.
//!
//! * [`DebugRanges`](./struct.DebugRanges.html): The `.debug_ranges` section.
//!
//! * [`DebugRngLists`](./struct.DebugRngLists.html): The `.debug_rnglists` section.
//!
//! * [`DebugStr`](./struct.DebugStr.html): The `.debug_str` section.
//!
//! * [`DebugStrOffsets`](./struct.DebugStrOffsets.html): The `.debug_str_offsets` section.
//!
//! * [`DebugTypes`](./struct.DebugTypes.html): The `.debug_types` section.
//!
//! * [`DebugCuIndex`](./struct.DebugCuIndex.html): The `.debug_cu_index` section.
//!
//! * [`DebugTuIndex`](./struct.DebugTuIndex.html): The `.debug_tu_index` section.
//!
//! * [`EhFrame`](./struct.EhFrame.html): The `.eh_frame` section.
//!
//! * [`EhFrameHdr`](./struct.EhFrameHdr.html): The `.eh_frame_hdr` section.
//!
//! * Each section type exposes methods for accessing the debugging data encoded
//! in that section. For example, the [`DebugInfo`](./struct.DebugInfo.html)
//! struct has the [`units`](./struct.DebugInfo.html#method.units) method for
//! iterating over the compilation units defined within it.
//!
//! * Offsets into a section are strongly typed: an offset into `.debug_info` is
//! the [`DebugInfoOffset`](./struct.DebugInfoOffset.html) type. It cannot be
//! used to index into the [`DebugLine`](./struct.DebugLine.html) type because
//! `DebugLine` represents the `.debug_line` section. There are similar types
//! for offsets relative to a compilation unit rather than a section.
//!
//! ## Using with `FallibleIterator`
//!
//! The standard library's `Iterator` trait and related APIs do not play well
//! with iterators where the `next` operation is fallible. One can make the
//! `Iterator`'s associated `Item` type be a `Result<T, E>`, however the
//! provided methods cannot gracefully handle the case when an `Err` is
//! returned.
//!
//! This situation led to the
//! [`fallible-iterator`](https://crates.io/crates/fallible-iterator) crate's
//! existence. You can read more of the rationale for its existence in its
//! docs. The crate provides the helpers you have come to expect (eg `map`,
//! `filter`, etc) for iterators that can fail.
//!
//! `gimli`'s many lazy parsing iterators are a perfect match for the
//! `fallible-iterator` crate's `FallibleIterator` trait because parsing is not
//! done eagerly. Parse errors later in the input might only be discovered after
//! having iterated through many items.
//!
//! To use `gimli` iterators with `FallibleIterator`, import the crate and trait
//! into your code:
//!
//! ```
//! # #[cfg(feature = "fallible-iterator")]
//! # fn foo() {
//! // Use the `FallibleIterator` trait so its methods are in scope!
//! use fallible_iterator::FallibleIterator;
//! use gimli::{DebugAranges, EndianSlice, LittleEndian};
//!
//! fn find_sum_of_address_range_lengths(aranges: DebugAranges<EndianSlice<LittleEndian>>)
//! -> gimli::Result<u64>
//! {
//! // `DebugAranges::headers` returns a `FallibleIterator`!
//! aranges.headers()
//! // `flat_map` is provided by `FallibleIterator`!
//! .flat_map(|header| Ok(header.entries()))
//! // `map` is provided by `FallibleIterator`!
//! .map(|arange| Ok(arange.length()))
//! // `fold` is provided by `FallibleIterator`!
//! .fold(0, |sum, len| Ok(sum + len))
//! }
//! # }
//! # fn main() {}
//! ```
use core::fmt::{self, Debug};
use core::result;
#[cfg(feature = "std")]
use std::{error, io};
use crate::common::{Register, SectionId};
use crate::constants;
mod util;
pub use util::*;
mod addr;
pub use self::addr::*;
mod cfi;
pub use self::cfi::*;
#[cfg(feature = "read")]
mod dwarf;
#[cfg(feature = "read")]
pub use self::dwarf::*;
mod endian_slice;
pub use self::endian_slice::*;
#[cfg(feature = "endian-reader")]
mod endian_reader;
#[cfg(feature = "endian-reader")]
pub use self::endian_reader::*;
mod reader;
pub use self::reader::*;
#[cfg(feature = "read")]
mod abbrev;
#[cfg(feature = "read")]
pub use self::abbrev::*;
mod aranges;
pub use self::aranges::*;
mod index;
pub use self::index::*;
#[cfg(feature = "read")]
mod line;
#[cfg(feature = "read")]
pub use self::line::*;
mod lists;
mod loclists;
pub use self::loclists::*;
#[cfg(feature = "read")]
mod lookup;
mod op;
pub use self::op::*;
#[cfg(feature = "read")]
mod pubnames;
#[cfg(feature = "read")]
pub use self::pubnames::*;
#[cfg(feature = "read")]
mod pubtypes;
#[cfg(feature = "read")]
pub use self::pubtypes::*;
mod rnglists;
pub use self::rnglists::*;
mod str;
pub use self::str::*;
/// An offset into the current compilation or type unit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct UnitOffset<T = usize>(pub T);
#[cfg(feature = "read")]
mod unit;
#[cfg(feature = "read")]
pub use self::unit::*;
mod value;
pub use self::value::*;
/// Indicates that storage should be allocated on heap.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StoreOnHeap;
/// `EndianBuf` has been renamed to `EndianSlice`. For ease of upgrading across
/// `gimli` versions, we export this type alias.
#[deprecated(note = "EndianBuf has been renamed to EndianSlice, use that instead.")]
pub type EndianBuf<'input, Endian> = EndianSlice<'input, Endian>;
/// An error that occurred when parsing.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
/// An I/O error occurred while reading.
Io,
/// Found a PC relative pointer, but the section base is undefined.
PcRelativePointerButSectionBaseIsUndefined,
/// Found a `.text` relative pointer, but the `.text` base is undefined.
TextRelativePointerButTextBaseIsUndefined,
/// Found a data relative pointer, but the data base is undefined.
DataRelativePointerButDataBaseIsUndefined,
/// Found a function relative pointer in a context that does not have a
/// function base.
FuncRelativePointerInBadContext,
/// Cannot parse a pointer with a `DW_EH_PE_omit` encoding.
CannotParseOmitPointerEncoding,
/// An error parsing an unsigned LEB128 value.
BadUnsignedLeb128,
/// An error parsing a signed LEB128 value.
BadSignedLeb128,
/// An abbreviation declared that its tag is zero, but zero is reserved for
/// null records.
AbbreviationTagZero,
/// An attribute specification declared that its form is zero, but zero is
/// reserved for null records.
AttributeFormZero,
/// The abbreviation's has-children byte was not one of
/// `DW_CHILDREN_{yes,no}`.
BadHasChildren,
/// The specified length is impossible.
BadLength,
/// Found an unknown `DW_FORM_*` type.
UnknownForm,
/// Expected a zero, found something else.
ExpectedZero,
/// Found an abbreviation code that has already been used.
DuplicateAbbreviationCode,
/// Found a duplicate arange.
DuplicateArange,
/// Found an unknown reserved length value.
UnknownReservedLength,
/// Found an unknown DWARF version.
UnknownVersion(u64),
/// Found a record with an unknown abbreviation code.
UnknownAbbreviation,
/// Hit the end of input before it was expected.
UnexpectedEof(ReaderOffsetId),
/// Read a null entry before it was expected.
UnexpectedNull,
/// Found an unknown standard opcode.
UnknownStandardOpcode(constants::DwLns),
/// Found an unknown extended opcode.
UnknownExtendedOpcode(constants::DwLne),
/// The specified address size is not supported.
UnsupportedAddressSize(u8),
/// The specified offset size is not supported.
UnsupportedOffsetSize(u8),
/// The specified field size is not supported.
UnsupportedFieldSize(u8),
/// The minimum instruction length must not be zero.
MinimumInstructionLengthZero,
/// The maximum operations per instruction must not be zero.
MaximumOperationsPerInstructionZero,
/// The line range must not be zero.
LineRangeZero,
/// The opcode base must not be zero.
OpcodeBaseZero,
/// Found an invalid UTF-8 string.
BadUtf8,
/// Expected to find the CIE ID, but found something else.
NotCieId,
/// Expected to find a pointer to a CIE, but found the CIE ID instead.
NotCiePointer,
/// Expected to find a pointer to an FDE, but found a CIE instead.
NotFdePointer,
/// Invalid branch target for a DW_OP_bra or DW_OP_skip.
BadBranchTarget(u64),
/// DW_OP_push_object_address used but no address passed in.
InvalidPushObjectAddress,
/// Not enough items on the stack when evaluating an expression.
NotEnoughStackItems,
/// Too many iterations to compute the expression.
TooManyIterations,
/// An unrecognized operation was found while parsing a DWARF
/// expression.
InvalidExpression(constants::DwOp),
/// An unsupported operation was found while evaluating a DWARF expression.
UnsupportedEvaluation,
/// The expression had a piece followed by an expression
/// terminator without a piece.
InvalidPiece,
/// An expression-terminating operation was followed by something
/// other than the end of the expression or a piece operation.
InvalidExpressionTerminator(u64),
/// Division or modulus by zero when evaluating an expression.
DivisionByZero,
/// An expression operation used mismatching types.
TypeMismatch,
/// An expression operation required an integral type but saw a
/// floating point type.
IntegralTypeRequired,
/// An expression operation used types that are not supported.
UnsupportedTypeOperation,
/// The shift value in an expression must be a non-negative integer.
InvalidShiftExpression,
/// An unknown DW_CFA_* instruction.
UnknownCallFrameInstruction(constants::DwCfa),
/// The end of an address range was before the beginning.
InvalidAddressRange,
/// The end offset of a loc list entry was before the beginning.
InvalidLocationAddressRange,
/// Encountered a call frame instruction in a context in which it is not
/// valid.
CfiInstructionInInvalidContext,
/// When evaluating call frame instructions, found a `DW_CFA_restore_state`
/// stack pop instruction, but the stack was empty, and had nothing to pop.
PopWithEmptyStack,
/// Do not have unwind info for the given address.
NoUnwindInfoForAddress,
/// An offset value was larger than the maximum supported value.
UnsupportedOffset,
/// The given pointer encoding is either unknown or invalid.
UnknownPointerEncoding,
/// Did not find an entry at the given offset.
NoEntryAtGivenOffset,
/// The given offset is out of bounds.
OffsetOutOfBounds,
/// Found an unknown CFI augmentation.
UnknownAugmentation,
/// We do not support the given pointer encoding yet.
UnsupportedPointerEncoding,
/// Registers larger than `u16` are not supported.
UnsupportedRegister(u64),
/// The CFI program defined more register rules than we have storage for.
TooManyRegisterRules,
/// Attempted to push onto the CFI or evaluation stack, but it was already
/// at full capacity.
StackFull,
/// The `.eh_frame_hdr` binary search table claims to be variable-length encoded,
/// which makes binary search impossible.
VariableLengthSearchTable,
/// The `DW_UT_*` value for this unit is not supported yet.
UnsupportedUnitType,
/// Ranges using AddressIndex are not supported yet.
UnsupportedAddressIndex,
/// Nonzero segment selector sizes aren't supported yet.
UnsupportedSegmentSize,
/// A compilation unit or type unit is missing its top level DIE.
MissingUnitDie,
/// A DIE attribute used an unsupported form.
UnsupportedAttributeForm,
/// Missing DW_LNCT_path in file entry format.
MissingFileEntryFormatPath,
/// Expected an attribute value to be a string form.
ExpectedStringAttributeValue,
/// `DW_FORM_implicit_const` used in an invalid context.
InvalidImplicitConst,
/// Invalid section count in `.dwp` index.
InvalidIndexSectionCount,
/// Invalid slot count in `.dwp` index.
InvalidIndexSlotCount,
/// Invalid hash row in `.dwp` index.
InvalidIndexRow,
/// Unknown section type in `.dwp` index.
UnknownIndexSection,
}
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> ::core::result::Result<(), fmt::Error> {
write!(f, "{}", self.description())
}
}
impl Error {
/// A short description of the error.
pub fn description(&self) -> &str {
match *self {
Error::Io => "An I/O error occurred while reading.",
Error::PcRelativePointerButSectionBaseIsUndefined => {
"Found a PC relative pointer, but the section base is undefined."
}
Error::TextRelativePointerButTextBaseIsUndefined => {
"Found a `.text` relative pointer, but the `.text` base is undefined."
}
Error::DataRelativePointerButDataBaseIsUndefined => {
"Found a data relative pointer, but the data base is undefined."
}
Error::FuncRelativePointerInBadContext => {
"Found a function relative pointer in a context that does not have a function base."
}
Error::CannotParseOmitPointerEncoding => {
"Cannot parse a pointer with a `DW_EH_PE_omit` encoding."
}
Error::BadUnsignedLeb128 => "An error parsing an unsigned LEB128 value",
Error::BadSignedLeb128 => "An error parsing a signed LEB128 value",
Error::AbbreviationTagZero => {
"An abbreviation declared that its tag is zero,
but zero is reserved for null records"
}
Error::AttributeFormZero => {
"An attribute specification declared that its form is zero,
but zero is reserved for null records"
}
Error::BadHasChildren => {
"The abbreviation's has-children byte was not one of
`DW_CHILDREN_{yes,no}`"
}
Error::BadLength => "The specified length is impossible",
Error::UnknownForm => "Found an unknown `DW_FORM_*` type",
Error::ExpectedZero => "Expected a zero, found something else",
Error::DuplicateAbbreviationCode => {
"Found an abbreviation code that has already been used"
}
Error::DuplicateArange => "Found a duplicate arange",
Error::UnknownReservedLength => "Found an unknown reserved length value",
Error::UnknownVersion(_) => "Found an unknown DWARF version",
Error::UnknownAbbreviation => "Found a record with an unknown abbreviation code",
Error::UnexpectedEof(_) => "Hit the end of input before it was expected",
Error::UnexpectedNull => "Read a null entry before it was expected.",
Error::UnknownStandardOpcode(_) => "Found an unknown standard opcode",
Error::UnknownExtendedOpcode(_) => "Found an unknown extended opcode",
Error::UnsupportedAddressSize(_) => "The specified address size is not supported",
Error::UnsupportedOffsetSize(_) => "The specified offset size is not supported",
Error::UnsupportedFieldSize(_) => "The specified field size is not supported",
Error::MinimumInstructionLengthZero => {
"The minimum instruction length must not be zero."
}
Error::MaximumOperationsPerInstructionZero => {
"The maximum operations per instruction must not be zero."
}
Error::LineRangeZero => "The line range must not be zero.",
Error::OpcodeBaseZero => "The opcode base must not be zero.",
Error::BadUtf8 => "Found an invalid UTF-8 string.",
Error::NotCieId => "Expected to find the CIE ID, but found something else.",
Error::NotCiePointer => "Expected to find a CIE pointer, but found the CIE ID instead.",
Error::NotFdePointer => {
"Expected to find an FDE pointer, but found a CIE pointer instead."
}
Error::BadBranchTarget(_) => "Invalid branch target in DWARF expression",
Error::InvalidPushObjectAddress => {
"DW_OP_push_object_address used but no object address given"
}
Error::NotEnoughStackItems => "Not enough items on stack when evaluating expression",
Error::TooManyIterations => "Too many iterations to evaluate DWARF expression",
Error::InvalidExpression(_) => "Invalid opcode in DWARF expression",
Error::UnsupportedEvaluation => "Unsupported operation when evaluating expression",
Error::InvalidPiece => {
"DWARF expression has piece followed by non-piece expression at end"
}
Error::InvalidExpressionTerminator(_) => "Expected DW_OP_piece or DW_OP_bit_piece",
Error::DivisionByZero => "Division or modulus by zero when evaluating expression",
Error::TypeMismatch => "Type mismatch when evaluating expression",
Error::IntegralTypeRequired => "Integral type expected when evaluating expression",
Error::UnsupportedTypeOperation => {
"An expression operation used types that are not supported"
}
Error::InvalidShiftExpression => {
"The shift value in an expression must be a non-negative integer."
}
Error::UnknownCallFrameInstruction(_) => "An unknown DW_CFA_* instructiion",
Error::InvalidAddressRange => {
"The end of an address range must not be before the beginning."
}
Error::InvalidLocationAddressRange => {
"The end offset of a location list entry must not be before the beginning."
}
Error::CfiInstructionInInvalidContext => {
"Encountered a call frame instruction in a context in which it is not valid."
}
Error::PopWithEmptyStack => {
"When evaluating call frame instructions, found a `DW_CFA_restore_state` stack pop \
instruction, but the stack was empty, and had nothing to pop."
}
Error::NoUnwindInfoForAddress => "Do not have unwind info for the given address.",
Error::UnsupportedOffset => {
"An offset value was larger than the maximum supported value."
}
Error::UnknownPointerEncoding => {
"The given pointer encoding is either unknown or invalid."
}
Error::NoEntryAtGivenOffset => "Did not find an entry at the given offset.",
Error::OffsetOutOfBounds => "The given offset is out of bounds.",
Error::UnknownAugmentation => "Found an unknown CFI augmentation.",
Error::UnsupportedPointerEncoding => {
"We do not support the given pointer encoding yet."
}
Error::UnsupportedRegister(_) => "Registers larger than `u16` are not supported.",
Error::TooManyRegisterRules => {
"The CFI program defined more register rules than we have storage for."
}
Error::StackFull => {
"Attempted to push onto the CFI stack, but it was already at full capacity."
}
Error::VariableLengthSearchTable => {
"The `.eh_frame_hdr` binary search table claims to be variable-length encoded, \
which makes binary search impossible."
}
Error::UnsupportedUnitType => "The `DW_UT_*` value for this unit is not supported yet",
Error::UnsupportedAddressIndex => "Ranges involving AddressIndex are not supported yet",
Error::UnsupportedSegmentSize => "Nonzero segment size not supported yet",
Error::MissingUnitDie => {
"A compilation unit or type unit is missing its top level DIE."
}
Error::UnsupportedAttributeForm => "A DIE attribute used an unsupported form.",
Error::MissingFileEntryFormatPath => "Missing DW_LNCT_path in file entry format.",
Error::ExpectedStringAttributeValue => {
"Expected an attribute value to be a string form."
}
Error::InvalidImplicitConst => "DW_FORM_implicit_const used in an invalid context.",
Error::InvalidIndexSectionCount => "Invalid section count in `.dwp` index.",
Error::InvalidIndexSlotCount => "Invalid slot count in `.dwp` index.",
Error::InvalidIndexRow => "Invalid hash row in `.dwp` index.",
Error::UnknownIndexSection => "Unknown section type in `.dwp` index.",
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {}
#[cfg(feature = "std")]
impl From<io::Error> for Error {
fn from(_: io::Error) -> Self {
Error::Io
}
}
/// The result of a parse.
pub type Result<T> = result::Result<T, Error>;
/// A convenience trait for loading DWARF sections from object files. To be
/// used like:
///
/// ```
/// use gimli::{DebugInfo, EndianSlice, LittleEndian, Reader, Section};
///
/// let buf = [0x00, 0x01, 0x02, 0x03];
/// let reader = EndianSlice::new(&buf, LittleEndian);
/// let loader = |name| -> Result<_, ()> { Ok(reader) };
///
/// let debug_info: DebugInfo<_> = Section::load(loader).unwrap();
/// ```
pub trait Section<R>: From<R> {
/// Returns the section id for this type.
fn id() -> SectionId;
/// Returns the ELF section name for this type.
fn section_name() -> &'static str {
Self::id().name()
}
/// Returns the ELF section name (if any) for this type when used in a dwo
/// file.
fn dwo_section_name() -> Option<&'static str> {
Self::id().dwo_name()
}
/// Returns the XCOFF section name (if any) for this type when used in a XCOFF
/// file.
fn xcoff_section_name() -> Option<&'static str> {
Self::id().xcoff_name()
}
/// Try to load the section using the given loader function.
fn load<F, E>(f: F) -> core::result::Result<Self, E>
where
F: FnOnce(SectionId) -> core::result::Result<R, E>,
{
f(Self::id()).map(From::from)
}
/// Returns the `Reader` for this section.
fn reader(&self) -> &R
where
R: Reader;
/// Returns the subrange of the section that is the contribution of
/// a unit in a `.dwp` file.
fn dwp_range(&self, offset: u32, size: u32) -> Result<Self>
where
R: Reader,
{
let mut data = self.reader().clone();
data.skip(R::Offset::from_u32(offset))?;
data.truncate(R::Offset::from_u32(size))?;
Ok(data.into())
}
/// Returns the `Reader` for this section.
fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)>
where
R: Reader,
{
self.reader()
.lookup_offset_id(id)
.map(|offset| (Self::id(), offset))
}
}
impl Register {
pub(crate) fn from_u64(x: u64) -> Result<Register> {
let y = x as u16;
if u64::from(y) == x {
Ok(Register(y))
} else {
Err(Error::UnsupportedRegister(x))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::common::Format;
use crate::endianity::LittleEndian;
use test_assembler::{Endian, Section};
#[test]
fn test_parse_initial_length_32_ok() {
let section = Section::with_endian(Endian::Little).L32(0x7856_3412);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_initial_length() {
Ok((length, format)) => {
assert_eq!(input.len(), 0);
assert_eq!(format, Format::Dwarf32);
assert_eq!(0x7856_3412, length);
}
otherwise => panic!("Unexpected result: {:?}", otherwise),
}
}
#[test]
fn test_parse_initial_length_64_ok() {
let section = Section::with_endian(Endian::Little)
// Dwarf_64_INITIAL_UNIT_LENGTH
.L32(0xffff_ffff)
// Actual length
.L64(0xffde_bc9a_7856_3412);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
#[cfg(target_pointer_width = "64")]
match input.read_initial_length() {
Ok((length, format)) => {
assert_eq!(input.len(), 0);
assert_eq!(format, Format::Dwarf64);
assert_eq!(0xffde_bc9a_7856_3412, length);
}
otherwise => panic!("Unexpected result: {:?}", otherwise),
}
#[cfg(target_pointer_width = "32")]
match input.read_initial_length() {
Err(Error::UnsupportedOffset) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
fn test_parse_initial_length_unknown_reserved_value() {
let section = Section::with_endian(Endian::Little).L32(0xffff_fffe);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_initial_length() {
Err(Error::UnknownReservedLength) => assert!(true),
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
fn test_parse_initial_length_incomplete() {
let buf = [0xff, 0xff, 0xff]; // Need at least 4 bytes.
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_initial_length() {
Err(Error::UnexpectedEof(_)) => assert!(true),
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
fn test_parse_initial_length_64_incomplete() {
let section = Section::with_endian(Endian::Little)
// Dwarf_64_INITIAL_UNIT_LENGTH
.L32(0xffff_ffff)
// Actual length is not long enough.
.L32(0x7856_3412);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_initial_length() {
Err(Error::UnexpectedEof(_)) => assert!(true),
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
fn test_parse_offset_32() {
let section = Section::with_endian(Endian::Little).L32(0x0123_4567);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_offset(Format::Dwarf32) {
Ok(val) => {
assert_eq!(input.len(), 0);
assert_eq!(val, 0x0123_4567);
}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
fn test_parse_offset_64_small() {
let section = Section::with_endian(Endian::Little).L64(0x0123_4567);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_offset(Format::Dwarf64) {
Ok(val) => {
assert_eq!(input.len(), 0);
assert_eq!(val, 0x0123_4567);
}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
#[cfg(target_pointer_width = "64")]
fn test_parse_offset_64_large() {
let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_offset(Format::Dwarf64) {
Ok(val) => {
assert_eq!(input.len(), 0);
assert_eq!(val, 0x0123_4567_89ab_cdef);
}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
#[test]
#[cfg(target_pointer_width = "32")]
fn test_parse_offset_64_large() {
let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
let buf = section.get_contents().unwrap();
let input = &mut EndianSlice::new(&buf, LittleEndian);
match input.read_offset(Format::Dwarf64) {
Err(Error::UnsupportedOffset) => assert!(true),
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
}
}

4140
vendor/gimli/src/read/op.rs vendored Normal file

File diff suppressed because it is too large Load Diff

141
vendor/gimli/src/read/pubnames.rs vendored Normal file
View File

@ -0,0 +1,141 @@
use crate::common::{DebugInfoOffset, SectionId};
use crate::endianity::Endianity;
use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser};
use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset};
/// A single parsed pubname.
#[derive(Debug, Clone)]
pub struct PubNamesEntry<R: Reader> {
unit_header_offset: DebugInfoOffset<R::Offset>,
die_offset: UnitOffset<R::Offset>,
name: R,
}
impl<R: Reader> PubNamesEntry<R> {
/// Returns the name this entry refers to.
pub fn name(&self) -> &R {
&self.name
}
/// Returns the offset into the .debug_info section for the header of the compilation unit
/// which contains this name.
pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> {
self.unit_header_offset
}
/// Returns the offset into the compilation unit for the debugging information entry which
/// has this name.
pub fn die_offset(&self) -> UnitOffset<R::Offset> {
self.die_offset
}
}
impl<R: Reader> PubStuffEntry<R> for PubNamesEntry<R> {
fn new(
die_offset: UnitOffset<R::Offset>,
name: R,
unit_header_offset: DebugInfoOffset<R::Offset>,
) -> Self {
PubNamesEntry {
unit_header_offset,
die_offset,
name,
}
}
}
/// The `DebugPubNames` struct represents the DWARF public names information
/// found in the `.debug_pubnames` section.
#[derive(Debug, Clone)]
pub struct DebugPubNames<R: Reader>(DebugLookup<R, PubStuffParser<R, PubNamesEntry<R>>>);
impl<'input, Endian> DebugPubNames<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugPubNames` instance from the data in the `.debug_pubnames`
/// section.
///
/// It is the caller's responsibility to read the `.debug_pubnames` section and
/// present it as a `&[u8]` slice. That means using some ELF loader on
/// Linux, a Mach-O loader on macOS, etc.
///
/// ```
/// use gimli::{DebugPubNames, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubnames_section_somehow = || &buf;
/// let debug_pubnames =
/// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian);
/// ```
pub fn new(debug_pubnames_section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(debug_pubnames_section, endian))
}
}
impl<R: Reader> DebugPubNames<R> {
/// Iterate the pubnames in the `.debug_pubnames` section.
///
/// ```
/// use gimli::{DebugPubNames, EndianSlice, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubnames_section_somehow = || &buf;
/// let debug_pubnames =
/// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian);
///
/// let mut iter = debug_pubnames.items();
/// while let Some(pubname) = iter.next().unwrap() {
/// println!("pubname {} found!", pubname.name().to_string_lossy());
/// }
/// ```
pub fn items(&self) -> PubNamesEntryIter<R> {
PubNamesEntryIter(self.0.items())
}
}
impl<R: Reader> Section<R> for DebugPubNames<R> {
fn id() -> SectionId {
SectionId::DebugPubNames
}
fn reader(&self) -> &R {
self.0.reader()
}
}
impl<R: Reader> From<R> for DebugPubNames<R> {
fn from(debug_pubnames_section: R) -> Self {
DebugPubNames(DebugLookup::from(debug_pubnames_section))
}
}
/// An iterator over the pubnames from a `.debug_pubnames` section.
///
/// Can be [used with
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
#[derive(Debug, Clone)]
pub struct PubNamesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubNamesEntry<R>>>);
impl<R: Reader> PubNamesEntryIter<R> {
/// Advance the iterator and return the next pubname.
///
/// Returns the newly parsed pubname as `Ok(Some(pubname))`. Returns
/// `Ok(None)` when iteration is complete and all pubnames have already been
/// parsed and yielded. If an error occurs while parsing the next pubname,
/// then this error is returned as `Err(e)`, and all subsequent calls return
/// `Ok(None)`.
pub fn next(&mut self) -> Result<Option<PubNamesEntry<R>>> {
self.0.next()
}
}
#[cfg(feature = "fallible-iterator")]
impl<R: Reader> fallible_iterator::FallibleIterator for PubNamesEntryIter<R> {
type Item = PubNamesEntry<R>;
type Error = crate::read::Error;
fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
self.0.next()
}
}

141
vendor/gimli/src/read/pubtypes.rs vendored Normal file
View File

@ -0,0 +1,141 @@
use crate::common::{DebugInfoOffset, SectionId};
use crate::endianity::Endianity;
use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser};
use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset};
/// A single parsed pubtype.
#[derive(Debug, Clone)]
pub struct PubTypesEntry<R: Reader> {
unit_header_offset: DebugInfoOffset<R::Offset>,
die_offset: UnitOffset<R::Offset>,
name: R,
}
impl<R: Reader> PubTypesEntry<R> {
/// Returns the name of the type this entry refers to.
pub fn name(&self) -> &R {
&self.name
}
/// Returns the offset into the .debug_info section for the header of the compilation unit
/// which contains the type with this name.
pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> {
self.unit_header_offset
}
/// Returns the offset into the compilation unit for the debugging information entry which
/// the type with this name.
pub fn die_offset(&self) -> UnitOffset<R::Offset> {
self.die_offset
}
}
impl<R: Reader> PubStuffEntry<R> for PubTypesEntry<R> {
fn new(
die_offset: UnitOffset<R::Offset>,
name: R,
unit_header_offset: DebugInfoOffset<R::Offset>,
) -> Self {
PubTypesEntry {
unit_header_offset,
die_offset,
name,
}
}
}
/// The `DebugPubTypes` struct represents the DWARF public types information
/// found in the `.debug_info` section.
#[derive(Debug, Clone)]
pub struct DebugPubTypes<R: Reader>(DebugLookup<R, PubStuffParser<R, PubTypesEntry<R>>>);
impl<'input, Endian> DebugPubTypes<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugPubTypes` instance from the data in the `.debug_pubtypes`
/// section.
///
/// It is the caller's responsibility to read the `.debug_pubtypes` section and
/// present it as a `&[u8]` slice. That means using some ELF loader on
/// Linux, a Mach-O loader on macOS, etc.
///
/// ```
/// use gimli::{DebugPubTypes, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubtypes_somehow = || &buf;
/// let debug_pubtypes =
/// DebugPubTypes::new(read_debug_pubtypes_somehow(), LittleEndian);
/// ```
pub fn new(debug_pubtypes_section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(debug_pubtypes_section, endian))
}
}
impl<R: Reader> DebugPubTypes<R> {
/// Iterate the pubtypes in the `.debug_pubtypes` section.
///
/// ```
/// use gimli::{DebugPubTypes, EndianSlice, LittleEndian};
///
/// # let buf = [];
/// # let read_debug_pubtypes_section_somehow = || &buf;
/// let debug_pubtypes =
/// DebugPubTypes::new(read_debug_pubtypes_section_somehow(), LittleEndian);
///
/// let mut iter = debug_pubtypes.items();
/// while let Some(pubtype) = iter.next().unwrap() {
/// println!("pubtype {} found!", pubtype.name().to_string_lossy());
/// }
/// ```
pub fn items(&self) -> PubTypesEntryIter<R> {
PubTypesEntryIter(self.0.items())
}
}
impl<R: Reader> Section<R> for DebugPubTypes<R> {
fn id() -> SectionId {
SectionId::DebugPubTypes
}
fn reader(&self) -> &R {
self.0.reader()
}
}
impl<R: Reader> From<R> for DebugPubTypes<R> {
fn from(debug_pubtypes_section: R) -> Self {
DebugPubTypes(DebugLookup::from(debug_pubtypes_section))
}
}
/// An iterator over the pubtypes from a `.debug_pubtypes` section.
///
/// Can be [used with
/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
#[derive(Debug, Clone)]
pub struct PubTypesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubTypesEntry<R>>>);
impl<R: Reader> PubTypesEntryIter<R> {
/// Advance the iterator and return the next pubtype.
///
/// Returns the newly parsed pubtype as `Ok(Some(pubtype))`. Returns
/// `Ok(None)` when iteration is complete and all pubtypes have already been
/// parsed and yielded. If an error occurs while parsing the next pubtype,
/// then this error is returned as `Err(e)`, and all subsequent calls return
/// `Ok(None)`.
pub fn next(&mut self) -> Result<Option<PubTypesEntry<R>>> {
self.0.next()
}
}
#[cfg(feature = "fallible-iterator")]
impl<R: Reader> fallible_iterator::FallibleIterator for PubTypesEntryIter<R> {
type Item = PubTypesEntry<R>;
type Error = crate::read::Error;
fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
self.0.next()
}
}

502
vendor/gimli/src/read/reader.rs vendored Normal file
View File

@ -0,0 +1,502 @@
#[cfg(feature = "read")]
use alloc::borrow::Cow;
use core::convert::TryInto;
use core::fmt::Debug;
use core::hash::Hash;
use core::ops::{Add, AddAssign, Sub};
use crate::common::Format;
use crate::endianity::Endianity;
use crate::leb128;
use crate::read::{Error, Result};
/// An identifier for an offset within a section reader.
///
/// This is used for error reporting. The meaning of this value is specific to
/// each reader implementation. The values should be chosen to be unique amongst
/// all readers. If values are not unique then errors may point to the wrong reader.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ReaderOffsetId(pub u64);
/// A trait for offsets with a DWARF section.
///
/// This allows consumers to choose a size that is appropriate for their address space.
pub trait ReaderOffset:
Debug + Copy + Eq + Ord + Hash + Add<Output = Self> + AddAssign + Sub<Output = Self>
{
/// Convert a u8 to an offset.
fn from_u8(offset: u8) -> Self;
/// Convert a u16 to an offset.
fn from_u16(offset: u16) -> Self;
/// Convert an i16 to an offset.
fn from_i16(offset: i16) -> Self;
/// Convert a u32 to an offset.
fn from_u32(offset: u32) -> Self;
/// Convert a u64 to an offset.
///
/// Returns `Error::UnsupportedOffset` if the value is too large.
fn from_u64(offset: u64) -> Result<Self>;
/// Convert an offset to a u64.
fn into_u64(self) -> u64;
/// Wrapping (modular) addition. Computes `self + other`.
fn wrapping_add(self, other: Self) -> Self;
/// Checked subtraction. Computes `self - other`.
fn checked_sub(self, other: Self) -> Option<Self>;
}
impl ReaderOffset for u64 {
#[inline]
fn from_u8(offset: u8) -> Self {
u64::from(offset)
}
#[inline]
fn from_u16(offset: u16) -> Self {
u64::from(offset)
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as u64
}
#[inline]
fn from_u32(offset: u32) -> Self {
u64::from(offset)
}
#[inline]
fn from_u64(offset: u64) -> Result<Self> {
Ok(offset)
}
#[inline]
fn into_u64(self) -> u64 {
self
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
impl ReaderOffset for u32 {
#[inline]
fn from_u8(offset: u8) -> Self {
u32::from(offset)
}
#[inline]
fn from_u16(offset: u16) -> Self {
u32::from(offset)
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as u32
}
#[inline]
fn from_u32(offset: u32) -> Self {
offset
}
#[inline]
fn from_u64(offset64: u64) -> Result<Self> {
let offset = offset64 as u32;
if u64::from(offset) == offset64 {
Ok(offset)
} else {
Err(Error::UnsupportedOffset)
}
}
#[inline]
fn into_u64(self) -> u64 {
u64::from(self)
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
impl ReaderOffset for usize {
#[inline]
fn from_u8(offset: u8) -> Self {
offset as usize
}
#[inline]
fn from_u16(offset: u16) -> Self {
offset as usize
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as usize
}
#[inline]
fn from_u32(offset: u32) -> Self {
offset as usize
}
#[inline]
fn from_u64(offset64: u64) -> Result<Self> {
let offset = offset64 as usize;
if offset as u64 == offset64 {
Ok(offset)
} else {
Err(Error::UnsupportedOffset)
}
}
#[inline]
fn into_u64(self) -> u64 {
self as u64
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
#[cfg(not(feature = "read"))]
pub(crate) mod seal_if_no_alloc {
#[derive(Debug)]
pub struct Sealed;
}
/// A trait for reading the data from a DWARF section.
///
/// All read operations advance the section offset of the reader
/// unless specified otherwise.
///
/// ## Choosing a `Reader` Implementation
///
/// `gimli` comes with a few different `Reader` implementations and lets you
/// choose the one that is right for your use case. A `Reader` is essentially a
/// view into the raw bytes that make up some DWARF, but this view might borrow
/// the underlying data or use reference counting ownership, and it might be
/// thread safe or not.
///
/// | Implementation | Ownership | Thread Safe | Notes |
/// |:------------------|:------------------|:------------|:------|
/// | [`EndianSlice`](./struct.EndianSlice.html) | Borrowed | Yes | Fastest, but requires that all of your code work with borrows. |
/// | [`EndianRcSlice`](./struct.EndianRcSlice.html) | Reference counted | No | Shared ownership via reference counting, which alleviates the borrow restrictions of `EndianSlice` but imposes reference counting increments and decrements. Cannot be sent across threads, because the reference count is not atomic. |
/// | [`EndianArcSlice`](./struct.EndianArcSlice.html) | Reference counted | Yes | The same as `EndianRcSlice`, but uses atomic reference counting, and therefore reference counting operations are slower but `EndianArcSlice`s may be sent across threads. |
/// | [`EndianReader<T>`](./struct.EndianReader.html) | Same as `T` | Same as `T` | Escape hatch for easily defining your own type of `Reader`. |
pub trait Reader: Debug + Clone {
/// The endianity of bytes that are read.
type Endian: Endianity;
/// The type used for offsets and lengths.
type Offset: ReaderOffset;
/// Return the endianity of bytes that are read.
fn endian(&self) -> Self::Endian;
/// Return the number of bytes remaining.
fn len(&self) -> Self::Offset;
/// Set the number of bytes remaining to zero.
fn empty(&mut self);
/// Set the number of bytes remaining to the specified length.
fn truncate(&mut self, len: Self::Offset) -> Result<()>;
/// Return the offset of this reader's data relative to the start of
/// the given base reader's data.
///
/// May panic if this reader's data is not contained within the given
/// base reader's data.
fn offset_from(&self, base: &Self) -> Self::Offset;
/// Return an identifier for the current reader offset.
fn offset_id(&self) -> ReaderOffsetId;
/// Return the offset corresponding to the given `id` if
/// it is associated with this reader.
fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>;
/// Find the index of the first occurrence of the given byte.
/// The offset of the reader is not changed.
fn find(&self, byte: u8) -> Result<Self::Offset>;
/// Discard the specified number of bytes.
fn skip(&mut self, len: Self::Offset) -> Result<()>;
/// Split a reader in two.
///
/// A new reader is returned that can be used to read the next
/// `len` bytes, and `self` is advanced so that it reads the remainder.
fn split(&mut self, len: Self::Offset) -> Result<Self>;
/// This trait cannot be implemented if "read" feature is not enabled.
///
/// `Reader` trait has a few methods that depend on `alloc` crate.
/// Disallowing `Reader` trait implementation prevents a crate that only depends on
/// "read-core" from being broken if another crate depending on `gimli` enables
/// "read" feature.
#[cfg(not(feature = "read"))]
fn cannot_implement() -> seal_if_no_alloc::Sealed;
/// Return all remaining data as a clone-on-write slice.
///
/// The slice will be borrowed where possible, but some readers may
/// always return an owned vector.
///
/// Does not advance the reader.
#[cfg(feature = "read")]
fn to_slice(&self) -> Result<Cow<[u8]>>;
/// Convert all remaining data to a clone-on-write string.
///
/// The string will be borrowed where possible, but some readers may
/// always return an owned string.
///
/// Does not advance the reader.
///
/// Returns an error if the data contains invalid characters.
#[cfg(feature = "read")]
fn to_string(&self) -> Result<Cow<str>>;
/// Convert all remaining data to a clone-on-write string, including invalid characters.
///
/// The string will be borrowed where possible, but some readers may
/// always return an owned string.
///
/// Does not advance the reader.
#[cfg(feature = "read")]
fn to_string_lossy(&self) -> Result<Cow<str>>;
/// Read exactly `buf.len()` bytes into `buf`.
fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>;
/// Read a u8 array.
#[inline]
fn read_u8_array<A>(&mut self) -> Result<A>
where
A: Sized + Default + AsMut<[u8]>,
{
let mut val = Default::default();
self.read_slice(<A as AsMut<[u8]>>::as_mut(&mut val))?;
Ok(val)
}
/// Return true if the number of bytes remaining is zero.
#[inline]
fn is_empty(&self) -> bool {
self.len() == Self::Offset::from_u8(0)
}
/// Read a u8.
#[inline]
fn read_u8(&mut self) -> Result<u8> {
let a: [u8; 1] = self.read_u8_array()?;
Ok(a[0])
}
/// Read an i8.
#[inline]
fn read_i8(&mut self) -> Result<i8> {
let a: [u8; 1] = self.read_u8_array()?;
Ok(a[0] as i8)
}
/// Read a u16.
#[inline]
fn read_u16(&mut self) -> Result<u16> {
let a: [u8; 2] = self.read_u8_array()?;
Ok(self.endian().read_u16(&a))
}
/// Read an i16.
#[inline]
fn read_i16(&mut self) -> Result<i16> {
let a: [u8; 2] = self.read_u8_array()?;
Ok(self.endian().read_i16(&a))
}
/// Read a u32.
#[inline]
fn read_u32(&mut self) -> Result<u32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_u32(&a))
}
/// Read an i32.
#[inline]
fn read_i32(&mut self) -> Result<i32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_i32(&a))
}
/// Read a u64.
#[inline]
fn read_u64(&mut self) -> Result<u64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_u64(&a))
}
/// Read an i64.
#[inline]
fn read_i64(&mut self) -> Result<i64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_i64(&a))
}
/// Read a f32.
#[inline]
fn read_f32(&mut self) -> Result<f32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_f32(&a))
}
/// Read a f64.
#[inline]
fn read_f64(&mut self) -> Result<f64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_f64(&a))
}
/// Read an unsigned n-bytes integer u64.
///
/// # Panics
///
/// Panics when nbytes < 1 or nbytes > 8
#[inline]
fn read_uint(&mut self, n: usize) -> Result<u64> {
let mut buf = [0; 8];
self.read_slice(&mut buf[..n])?;
Ok(self.endian().read_uint(&buf[..n]))
}
/// Read a null-terminated slice, and return it (excluding the null).
fn read_null_terminated_slice(&mut self) -> Result<Self> {
let idx = self.find(0)?;
let val = self.split(idx)?;
self.skip(Self::Offset::from_u8(1))?;
Ok(val)
}
/// Skip a LEB128 encoded integer.
fn skip_leb128(&mut self) -> Result<()> {
leb128::read::skip(self)
}
/// Read an unsigned LEB128 encoded integer.
fn read_uleb128(&mut self) -> Result<u64> {
leb128::read::unsigned(self)
}
/// Read an unsigned LEB128 encoded u32.
fn read_uleb128_u32(&mut self) -> Result<u32> {
leb128::read::unsigned(self)?
.try_into()
.map_err(|_| Error::BadUnsignedLeb128)
}
/// Read an unsigned LEB128 encoded u16.
fn read_uleb128_u16(&mut self) -> Result<u16> {
leb128::read::u16(self)
}
/// Read a signed LEB128 encoded integer.
fn read_sleb128(&mut self) -> Result<i64> {
leb128::read::signed(self)
}
/// Read an initial length field.
///
/// This field is encoded as either a 32-bit length or
/// a 64-bit length, and the returned `Format` indicates which.
fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> {
const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0;
const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff;
let val = self.read_u32()?;
if val < MAX_DWARF_32_UNIT_LENGTH {
Ok((Self::Offset::from_u32(val), Format::Dwarf32))
} else if val == DWARF_64_INITIAL_UNIT_LENGTH {
let val = self.read_u64().and_then(Self::Offset::from_u64)?;
Ok((val, Format::Dwarf64))
} else {
Err(Error::UnknownReservedLength)
}
}
/// Read an address-sized integer, and return it as a `u64`.
fn read_address(&mut self, address_size: u8) -> Result<u64> {
match address_size {
1 => self.read_u8().map(u64::from),
2 => self.read_u16().map(u64::from),
4 => self.read_u32().map(u64::from),
8 => self.read_u64(),
otherwise => Err(Error::UnsupportedAddressSize(otherwise)),
}
}
/// Parse a word-sized integer according to the DWARF format.
///
/// These are always used to encode section offsets or lengths,
/// and so have a type of `Self::Offset`.
fn read_word(&mut self, format: Format) -> Result<Self::Offset> {
match format {
Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32),
Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64),
}
}
/// Parse a word-sized section length according to the DWARF format.
#[inline]
fn read_length(&mut self, format: Format) -> Result<Self::Offset> {
self.read_word(format)
}
/// Parse a word-sized section offset according to the DWARF format.
#[inline]
fn read_offset(&mut self, format: Format) -> Result<Self::Offset> {
self.read_word(format)
}
/// Parse a section offset of the given size.
///
/// This is used for `DW_FORM_ref_addr` values in DWARF version 2.
fn read_sized_offset(&mut self, size: u8) -> Result<Self::Offset> {
match size {
1 => self.read_u8().map(u64::from),
2 => self.read_u16().map(u64::from),
4 => self.read_u32().map(u64::from),
8 => self.read_u64(),
otherwise => Err(Error::UnsupportedOffsetSize(otherwise)),
}
.and_then(Self::Offset::from_u64)
}
}

1458
vendor/gimli/src/read/rnglists.rs vendored Normal file

File diff suppressed because it is too large Load Diff

321
vendor/gimli/src/read/str.rs vendored Normal file
View File

@ -0,0 +1,321 @@
use crate::common::{
DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsBase, DebugStrOffsetsIndex, DwarfFileType,
Encoding, SectionId,
};
use crate::endianity::Endianity;
use crate::read::{EndianSlice, Reader, ReaderOffset, Result, Section};
use crate::Format;
/// The `DebugStr` struct represents the DWARF strings
/// found in the `.debug_str` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugStr<R> {
debug_str_section: R,
}
impl<'input, Endian> DebugStr<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugStr` instance from the data in the `.debug_str`
/// section.
///
/// It is the caller's responsibility to read the `.debug_str` section and
/// present it as a `&[u8]` slice. That means using some ELF loader on
/// Linux, a Mach-O loader on macOS, etc.
///
/// ```
/// use gimli::{DebugStr, LittleEndian};
///
/// # let buf = [0x00, 0x01, 0x02, 0x03];
/// # let read_debug_str_section_somehow = || &buf;
/// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
/// ```
pub fn new(debug_str_section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(debug_str_section, endian))
}
}
impl<R: Reader> DebugStr<R> {
/// Lookup a string from the `.debug_str` section by DebugStrOffset.
///
/// ```
/// use gimli::{DebugStr, DebugStrOffset, LittleEndian};
///
/// # let buf = [0x01, 0x02, 0x00];
/// # let offset = DebugStrOffset(0);
/// # let read_debug_str_section_somehow = || &buf;
/// # let debug_str_offset_somehow = || offset;
/// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
/// println!("Found string {:?}", debug_str.get_str(debug_str_offset_somehow()));
/// ```
pub fn get_str(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
let input = &mut self.debug_str_section.clone();
input.skip(offset.0)?;
input.read_null_terminated_slice()
}
}
impl<T> DebugStr<T> {
/// Create a `DebugStr` section that references the data in `self`.
///
/// This is useful when `R` implements `Reader` but `T` does not.
///
/// ## Example Usage
///
/// ```rust,no_run
/// # let load_section = || unimplemented!();
/// // Read the DWARF section into a `Vec` with whatever object loader you're using.
/// let owned_section: gimli::DebugStr<Vec<u8>> = load_section();
/// // Create a reference to the DWARF section.
/// let section = owned_section.borrow(|section| {
/// gimli::EndianSlice::new(&section, gimli::LittleEndian)
/// });
/// ```
pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr<R>
where
F: FnMut(&'a T) -> R,
{
borrow(&self.debug_str_section).into()
}
}
impl<R> Section<R> for DebugStr<R> {
fn id() -> SectionId {
SectionId::DebugStr
}
fn reader(&self) -> &R {
&self.debug_str_section
}
}
impl<R> From<R> for DebugStr<R> {
fn from(debug_str_section: R) -> Self {
DebugStr { debug_str_section }
}
}
/// The raw contents of the `.debug_str_offsets` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugStrOffsets<R> {
section: R,
}
impl<R: Reader> DebugStrOffsets<R> {
// TODO: add an iterator over the sets of entries in the section.
// This is not needed for common usage of the section though.
/// Returns the `.debug_str` offset at the given `base` and `index`.
///
/// A set of entries in the `.debug_str_offsets` section consists of a header
/// followed by a series of string table offsets.
///
/// The `base` must be the `DW_AT_str_offsets_base` value from the compilation unit DIE.
/// This is an offset that points to the first entry following the header.
///
/// The `index` is the value of a `DW_FORM_strx` attribute.
///
/// The `format` must be the DWARF format of the compilation unit. This format must
/// match the header. However, note that we do not parse the header to validate this,
/// since locating the header is unreliable, and the GNU extensions do not emit it.
pub fn get_str_offset(
&self,
format: Format,
base: DebugStrOffsetsBase<R::Offset>,
index: DebugStrOffsetsIndex<R::Offset>,
) -> Result<DebugStrOffset<R::Offset>> {
let input = &mut self.section.clone();
input.skip(base.0)?;
input.skip(R::Offset::from_u64(
index.0.into_u64() * u64::from(format.word_size()),
)?)?;
input.read_offset(format).map(DebugStrOffset)
}
}
impl<T> DebugStrOffsets<T> {
/// Create a `DebugStrOffsets` section that references the data in `self`.
///
/// This is useful when `R` implements `Reader` but `T` does not.
///
/// ## Example Usage
///
/// ```rust,no_run
/// # let load_section = || unimplemented!();
/// // Read the DWARF section into a `Vec` with whatever object loader you're using.
/// let owned_section: gimli::DebugStrOffsets<Vec<u8>> = load_section();
/// // Create a reference to the DWARF section.
/// let section = owned_section.borrow(|section| {
/// gimli::EndianSlice::new(&section, gimli::LittleEndian)
/// });
/// ```
pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets<R>
where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
impl<R> Section<R> for DebugStrOffsets<R> {
fn id() -> SectionId {
SectionId::DebugStrOffsets
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugStrOffsets<R> {
fn from(section: R) -> Self {
DebugStrOffsets { section }
}
}
impl<Offset> DebugStrOffsetsBase<Offset>
where
Offset: ReaderOffset,
{
/// Returns a `DebugStrOffsetsBase` with the default value of DW_AT_str_offsets_base
/// for the given `Encoding` and `DwarfFileType`.
pub fn default_for_encoding_and_file(
encoding: Encoding,
file_type: DwarfFileType,
) -> DebugStrOffsetsBase<Offset> {
if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
// In .dwo files, the compiler omits the DW_AT_str_offsets_base attribute (because there is
// only a single unit in the file) but we must skip past the header, which the attribute
// would normally do for us.
// initial_length_size + version + 2 bytes of padding.
DebugStrOffsetsBase(Offset::from_u8(
encoding.format.initial_length_size() + 2 + 2,
))
} else {
DebugStrOffsetsBase(Offset::from_u8(0))
}
}
}
/// The `DebugLineStr` struct represents the DWARF strings
/// found in the `.debug_line_str` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugLineStr<R> {
section: R,
}
impl<'input, Endian> DebugLineStr<EndianSlice<'input, Endian>>
where
Endian: Endianity,
{
/// Construct a new `DebugLineStr` instance from the data in the `.debug_line_str`
/// section.
///
/// It is the caller's responsibility to read the `.debug_line_str` section and
/// present it as a `&[u8]` slice. That means using some ELF loader on
/// Linux, a Mach-O loader on macOS, etc.
///
/// ```
/// use gimli::{DebugLineStr, LittleEndian};
///
/// # let buf = [0x00, 0x01, 0x02, 0x03];
/// # let read_debug_line_str_section_somehow = || &buf;
/// let debug_str = DebugLineStr::new(read_debug_line_str_section_somehow(), LittleEndian);
/// ```
pub fn new(debug_line_str_section: &'input [u8], endian: Endian) -> Self {
Self::from(EndianSlice::new(debug_line_str_section, endian))
}
}
impl<R: Reader> DebugLineStr<R> {
/// Lookup a string from the `.debug_line_str` section by DebugLineStrOffset.
pub fn get_str(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
let input = &mut self.section.clone();
input.skip(offset.0)?;
input.read_null_terminated_slice()
}
}
impl<T> DebugLineStr<T> {
/// Create a `DebugLineStr` section that references the data in `self`.
///
/// This is useful when `R` implements `Reader` but `T` does not.
///
/// ## Example Usage
///
/// ```rust,no_run
/// # let load_section = || unimplemented!();
/// // Read the DWARF section into a `Vec` with whatever object loader you're using.
/// let owned_section: gimli::DebugLineStr<Vec<u8>> = load_section();
/// // Create a reference to the DWARF section.
/// let section = owned_section.borrow(|section| {
/// gimli::EndianSlice::new(&section, gimli::LittleEndian)
/// });
/// ```
pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr<R>
where
F: FnMut(&'a T) -> R,
{
borrow(&self.section).into()
}
}
impl<R> Section<R> for DebugLineStr<R> {
fn id() -> SectionId {
SectionId::DebugLineStr
}
fn reader(&self) -> &R {
&self.section
}
}
impl<R> From<R> for DebugLineStr<R> {
fn from(section: R) -> Self {
DebugLineStr { section }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_util::GimliSectionMethods;
use crate::LittleEndian;
use test_assembler::{Endian, Label, LabelMaker, Section};
#[test]
fn test_get_str_offset() {
for format in vec![Format::Dwarf32, Format::Dwarf64] {
let zero = Label::new();
let length = Label::new();
let start = Label::new();
let first = Label::new();
let end = Label::new();
let mut section = Section::with_endian(Endian::Little)
.mark(&zero)
.initial_length(format, &length, &start)
.D16(5)
.D16(0)
.mark(&first);
for i in 0..20 {
section = section.word(format.word_size(), 1000 + i);
}
section = section.mark(&end);
length.set_const((&end - &start) as u64);
let section = section.get_contents().unwrap();
let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(&section, LittleEndian));
let base = DebugStrOffsetsBase((&first - &zero) as usize);
assert_eq!(
debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(0)),
Ok(DebugStrOffset(1000))
);
assert_eq!(
debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(19)),
Ok(DebugStrOffset(1019))
);
}
}
}

6139
vendor/gimli/src/read/unit.rs vendored Normal file

File diff suppressed because it is too large Load Diff

283
vendor/gimli/src/read/util.rs vendored Normal file
View File

@ -0,0 +1,283 @@
#[cfg(feature = "read")]
use alloc::boxed::Box;
#[cfg(feature = "read")]
use alloc::vec::Vec;
use core::fmt;
use core::mem::MaybeUninit;
use core::ops;
use core::ptr;
use core::slice;
mod sealed {
/// # Safety
/// Implementer must not modify the content in storage.
pub unsafe trait Sealed {
type Storage;
fn new_storage() -> Self::Storage;
fn grow(_storage: &mut Self::Storage, _additional: usize) -> Result<(), CapacityFull> {
Err(CapacityFull)
}
}
#[derive(Clone, Copy, Debug)]
pub struct CapacityFull;
}
use sealed::*;
/// Marker trait for types that can be used as backing storage when a growable array type is needed.
///
/// This trait is sealed and cannot be implemented for types outside this crate.
pub trait ArrayLike: Sealed {
/// Type of the elements being stored.
type Item;
#[doc(hidden)]
fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<Self::Item>];
#[doc(hidden)]
fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<Self::Item>];
}
// Use macro since const generics can't be used due to MSRV.
macro_rules! impl_array {
() => {};
($n:literal $($rest:tt)*) => {
// SAFETY: does not modify the content in storage.
unsafe impl<T> Sealed for [T; $n] {
type Storage = [MaybeUninit<T>; $n];
fn new_storage() -> Self::Storage {
// SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid.
unsafe { MaybeUninit::uninit().assume_init() }
}
}
impl<T> ArrayLike for [T; $n] {
type Item = T;
fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<T>] {
storage
}
fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<T>] {
storage
}
}
impl_array!($($rest)*);
}
}
#[cfg(feature = "read")]
macro_rules! impl_box {
() => {};
($n:literal $($rest:tt)*) => {
// SAFETY: does not modify the content in storage.
unsafe impl<T> Sealed for Box<[T; $n]> {
type Storage = Box<[MaybeUninit<T>; $n]>;
fn new_storage() -> Self::Storage {
// SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid.
Box::new(unsafe { MaybeUninit::uninit().assume_init() })
}
}
impl<T> ArrayLike for Box<[T; $n]> {
type Item = T;
fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<T>] {
&storage[..]
}
fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<T>] {
&mut storage[..]
}
}
impl_box!($($rest)*);
}
}
impl_array!(0 1 2 3 4 8 16 32 64 128 192);
#[cfg(feature = "read")]
impl_box!(0 1 2 3 4 8 16 32 64 128 192);
#[cfg(feature = "read")]
unsafe impl<T> Sealed for Vec<T> {
type Storage = Box<[MaybeUninit<T>]>;
fn new_storage() -> Self::Storage {
Box::new([])
}
fn grow(storage: &mut Self::Storage, additional: usize) -> Result<(), CapacityFull> {
let mut vec: Vec<_> = core::mem::replace(storage, Box::new([])).into();
vec.reserve(additional);
// SAFETY: This is a `Vec` of `MaybeUninit`.
unsafe { vec.set_len(vec.capacity()) };
*storage = vec.into_boxed_slice();
Ok(())
}
}
#[cfg(feature = "read")]
impl<T> ArrayLike for Vec<T> {
type Item = T;
fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<T>] {
storage
}
fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<T>] {
storage
}
}
pub(crate) struct ArrayVec<A: ArrayLike> {
storage: A::Storage,
len: usize,
}
impl<A: ArrayLike> ArrayVec<A> {
pub fn new() -> Self {
Self {
storage: A::new_storage(),
len: 0,
}
}
pub fn clear(&mut self) {
let ptr: *mut [A::Item] = &mut **self;
// Set length first so the type invariant is upheld even if `drop_in_place` panicks.
self.len = 0;
// SAFETY: `ptr` contains valid elements only and we "forget" them by setting the length.
unsafe { ptr::drop_in_place(ptr) };
}
pub fn try_push(&mut self, value: A::Item) -> Result<(), CapacityFull> {
let mut storage = A::as_mut_slice(&mut self.storage);
if self.len >= storage.len() {
A::grow(&mut self.storage, 1)?;
storage = A::as_mut_slice(&mut self.storage);
}
storage[self.len] = MaybeUninit::new(value);
self.len += 1;
Ok(())
}
pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityFull> {
assert!(index <= self.len);
let mut storage = A::as_mut_slice(&mut self.storage);
if self.len >= storage.len() {
A::grow(&mut self.storage, 1)?;
storage = A::as_mut_slice(&mut self.storage);
}
// SAFETY: storage[index] is filled later.
unsafe {
let p = storage.as_mut_ptr().add(index);
core::ptr::copy(p as *const _, p.add(1), self.len - index);
}
storage[index] = MaybeUninit::new(element);
self.len += 1;
Ok(())
}
pub fn pop(&mut self) -> Option<A::Item> {
if self.len == 0 {
None
} else {
self.len -= 1;
// SAFETY: this element is valid and we "forget" it by setting the length.
Some(unsafe { A::as_slice(&self.storage)[self.len].as_ptr().read() })
}
}
pub fn swap_remove(&mut self, index: usize) -> A::Item {
assert!(self.len > 0);
A::as_mut_slice(&mut self.storage).swap(index, self.len - 1);
self.pop().unwrap()
}
}
#[cfg(feature = "read")]
impl<T> ArrayVec<Vec<T>> {
pub fn into_vec(mut self) -> Vec<T> {
let len = core::mem::replace(&mut self.len, 0);
let storage = core::mem::replace(&mut self.storage, Box::new([]));
let slice = Box::leak(storage);
debug_assert!(len <= slice.len());
// SAFETY: valid elements.
unsafe { Vec::from_raw_parts(slice.as_mut_ptr() as *mut T, len, slice.len()) }
}
}
impl<A: ArrayLike> Drop for ArrayVec<A> {
fn drop(&mut self) {
self.clear();
}
}
impl<A: ArrayLike> Default for ArrayVec<A> {
fn default() -> Self {
Self::new()
}
}
impl<A: ArrayLike> ops::Deref for ArrayVec<A> {
type Target = [A::Item];
fn deref(&self) -> &[A::Item] {
let slice = &A::as_slice(&self.storage);
debug_assert!(self.len <= slice.len());
// SAFETY: valid elements.
unsafe { slice::from_raw_parts(slice.as_ptr() as _, self.len) }
}
}
impl<A: ArrayLike> ops::DerefMut for ArrayVec<A> {
fn deref_mut(&mut self) -> &mut [A::Item] {
let slice = &mut A::as_mut_slice(&mut self.storage);
debug_assert!(self.len <= slice.len());
// SAFETY: valid elements.
unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr() as _, self.len) }
}
}
impl<A: ArrayLike> Clone for ArrayVec<A>
where
A::Item: Clone,
{
fn clone(&self) -> Self {
let mut new = Self::default();
for value in &**self {
new.try_push(value.clone()).unwrap();
}
new
}
}
impl<A: ArrayLike> PartialEq for ArrayVec<A>
where
A::Item: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<A: ArrayLike> Eq for ArrayVec<A> where A::Item: Eq {}
impl<A: ArrayLike> fmt::Debug for ArrayVec<A>
where
A::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}

1621
vendor/gimli/src/read/value.rs vendored Normal file

File diff suppressed because it is too large Load Diff

53
vendor/gimli/src/test_util.rs vendored Normal file
View File

@ -0,0 +1,53 @@
#![allow(missing_docs)]
use crate::Format;
use test_assembler::{Label, Section};
pub trait GimliSectionMethods {
fn sleb(self, val: i64) -> Self;
fn uleb(self, val: u64) -> Self;
fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self;
fn word(self, size: u8, val: u64) -> Self;
fn word_label(self, size: u8, val: &Label) -> Self;
}
impl GimliSectionMethods for Section {
fn sleb(mut self, mut val: i64) -> Self {
while val & !0x3f != 0 && val | 0x3f != -1 {
self = self.D8(val as u8 | 0x80);
val >>= 7;
}
self.D8(val as u8 & 0x7f)
}
fn uleb(mut self, mut val: u64) -> Self {
while val & !0x7f != 0 {
self = self.D8(val as u8 | 0x80);
val >>= 7;
}
self.D8(val as u8)
}
fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self {
match format {
Format::Dwarf32 => self.D32(length).mark(start),
Format::Dwarf64 => self.D32(0xffff_ffff).D64(length).mark(start),
}
}
fn word(self, size: u8, val: u64) -> Self {
match size {
4 => self.D32(val as u32),
8 => self.D64(val),
_ => panic!("unsupported word size"),
}
}
fn word_label(self, size: u8, val: &Label) -> Self {
match size {
4 => self.D32(val),
8 => self.D64(val),
_ => panic!("unsupported word size"),
}
}
}

188
vendor/gimli/src/write/abbrev.rs vendored Normal file
View File

@ -0,0 +1,188 @@
use alloc::vec::Vec;
use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use crate::common::{DebugAbbrevOffset, SectionId};
use crate::constants;
use crate::write::{Result, Section, Writer};
/// A table of abbreviations that will be stored in a `.debug_abbrev` section.
// Requirements:
// - values are `Abbreviation`
// - insertion returns an abbreviation code for use in writing a DIE
// - inserting a duplicate returns the code of the existing value
#[derive(Debug, Default)]
pub(crate) struct AbbreviationTable {
abbrevs: IndexSet<Abbreviation>,
}
impl AbbreviationTable {
/// Add an abbreviation to the table and return its code.
pub fn add(&mut self, abbrev: Abbreviation) -> u64 {
let (code, _) = self.abbrevs.insert_full(abbrev);
// Code must be non-zero
(code + 1) as u64
}
/// Write the abbreviation table to the `.debug_abbrev` section.
pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
for (code, abbrev) in self.abbrevs.iter().enumerate() {
w.write_uleb128((code + 1) as u64)?;
abbrev.write(w)?;
}
// Null abbreviation code
w.write_u8(0)
}
}
/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
/// its tag type, whether it has children, and its set of attributes.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct Abbreviation {
tag: constants::DwTag,
has_children: bool,
attributes: Vec<AttributeSpecification>,
}
impl Abbreviation {
/// Construct a new `Abbreviation`.
#[inline]
pub fn new(
tag: constants::DwTag,
has_children: bool,
attributes: Vec<AttributeSpecification>,
) -> Abbreviation {
Abbreviation {
tag,
has_children,
attributes,
}
}
/// Write the abbreviation to the `.debug_abbrev` section.
pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
w.write_uleb128(self.tag.0.into())?;
w.write_u8(if self.has_children {
constants::DW_CHILDREN_yes.0
} else {
constants::DW_CHILDREN_no.0
})?;
for attr in &self.attributes {
attr.write(w)?;
}
// Null name and form
w.write_u8(0)?;
w.write_u8(0)
}
}
/// The description of an attribute in an abbreviated type.
// TODO: support implicit const
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct AttributeSpecification {
name: constants::DwAt,
form: constants::DwForm,
}
impl AttributeSpecification {
/// Construct a new `AttributeSpecification`.
#[inline]
pub fn new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification {
AttributeSpecification { name, form }
}
/// Write the attribute specification to the `.debug_abbrev` section.
#[inline]
pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
w.write_uleb128(self.name.0.into())?;
w.write_uleb128(self.form.0.into())
}
}
define_section!(
DebugAbbrev,
DebugAbbrevOffset,
"A writable `.debug_abbrev` section."
);
#[cfg(test)]
#[cfg(feature = "read")]
mod tests {
use super::*;
use crate::constants;
use crate::read;
use crate::write::EndianVec;
use crate::LittleEndian;
#[test]
fn test_abbreviation_table() {
let mut abbrevs = AbbreviationTable::default();
let abbrev1 = Abbreviation::new(
constants::DW_TAG_subprogram,
false,
vec![AttributeSpecification::new(
constants::DW_AT_name,
constants::DW_FORM_string,
)],
);
let abbrev2 = Abbreviation::new(
constants::DW_TAG_compile_unit,
true,
vec![
AttributeSpecification::new(constants::DW_AT_producer, constants::DW_FORM_strp),
AttributeSpecification::new(constants::DW_AT_language, constants::DW_FORM_data2),
],
);
let code1 = abbrevs.add(abbrev1.clone());
assert_eq!(code1, 1);
let code2 = abbrevs.add(abbrev2.clone());
assert_eq!(code2, 2);
assert_eq!(abbrevs.add(abbrev1.clone()), code1);
assert_eq!(abbrevs.add(abbrev2.clone()), code2);
let mut debug_abbrev = DebugAbbrev::from(EndianVec::new(LittleEndian));
let debug_abbrev_offset = debug_abbrev.offset();
assert_eq!(debug_abbrev_offset, DebugAbbrevOffset(0));
abbrevs.write(&mut debug_abbrev).unwrap();
assert_eq!(debug_abbrev.offset(), DebugAbbrevOffset(17));
let read_debug_abbrev = read::DebugAbbrev::new(debug_abbrev.slice(), LittleEndian);
let read_abbrevs = read_debug_abbrev
.abbreviations(debug_abbrev_offset)
.unwrap();
let read_abbrev1 = read_abbrevs.get(code1).unwrap();
assert_eq!(abbrev1.tag, read_abbrev1.tag());
assert_eq!(abbrev1.has_children, read_abbrev1.has_children());
assert_eq!(abbrev1.attributes.len(), read_abbrev1.attributes().len());
assert_eq!(
abbrev1.attributes[0].name,
read_abbrev1.attributes()[0].name()
);
assert_eq!(
abbrev1.attributes[0].form,
read_abbrev1.attributes()[0].form()
);
let read_abbrev2 = read_abbrevs.get(code2).unwrap();
assert_eq!(abbrev2.tag, read_abbrev2.tag());
assert_eq!(abbrev2.has_children, read_abbrev2.has_children());
assert_eq!(abbrev2.attributes.len(), read_abbrev2.attributes().len());
assert_eq!(
abbrev2.attributes[0].name,
read_abbrev2.attributes()[0].name()
);
assert_eq!(
abbrev2.attributes[0].form,
read_abbrev2.attributes()[0].form()
);
assert_eq!(
abbrev2.attributes[1].name,
read_abbrev2.attributes()[1].name()
);
assert_eq!(
abbrev2.attributes[1].form,
read_abbrev2.attributes()[1].form()
);
}
}

1050
vendor/gimli/src/write/cfi.rs vendored Normal file

File diff suppressed because it is too large Load Diff

138
vendor/gimli/src/write/dwarf.rs vendored Normal file
View File

@ -0,0 +1,138 @@
use alloc::vec::Vec;
use crate::common::Encoding;
use crate::write::{
AbbreviationTable, LineProgram, LineStringTable, Result, Sections, StringTable, Unit,
UnitTable, Writer,
};
/// Writable DWARF information for more than one unit.
#[derive(Debug, Default)]
pub struct Dwarf {
/// A table of units. These are primarily stored in the `.debug_info` section,
/// but they also contain information that is stored in other sections.
pub units: UnitTable,
/// Extra line number programs that are not associated with a unit.
///
/// These should only be used when generating DWARF5 line-only debug
/// information.
pub line_programs: Vec<LineProgram>,
/// A table of strings that will be stored in the `.debug_line_str` section.
pub line_strings: LineStringTable,
/// A table of strings that will be stored in the `.debug_str` section.
pub strings: StringTable,
}
impl Dwarf {
/// Create a new `Dwarf` instance.
#[inline]
pub fn new() -> Self {
Self::default()
}
/// Write the DWARF information to the given sections.
pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
let strings = self.strings.write(&mut sections.debug_str)?;
self.units.write(sections, &line_strings, &strings)?;
for line_program in &self.line_programs {
line_program.write(
&mut sections.debug_line,
line_program.encoding(),
&line_strings,
&strings,
)?;
}
Ok(())
}
}
/// Writable DWARF information for a single unit.
#[derive(Debug)]
pub struct DwarfUnit {
/// A unit. This is primarily stored in the `.debug_info` section,
/// but also contains information that is stored in other sections.
pub unit: Unit,
/// A table of strings that will be stored in the `.debug_line_str` section.
pub line_strings: LineStringTable,
/// A table of strings that will be stored in the `.debug_str` section.
pub strings: StringTable,
}
impl DwarfUnit {
/// Create a new `DwarfUnit`.
///
/// Note: you should set `self.unit.line_program` after creation.
/// This cannot be done earlier because it may need to reference
/// `self.line_strings`.
pub fn new(encoding: Encoding) -> Self {
let unit = Unit::new(encoding, LineProgram::none());
DwarfUnit {
unit,
line_strings: LineStringTable::default(),
strings: StringTable::default(),
}
}
/// Write the DWARf information to the given sections.
pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
let strings = self.strings.write(&mut sections.debug_str)?;
let abbrev_offset = sections.debug_abbrev.offset();
let mut abbrevs = AbbreviationTable::default();
self.unit.write(
sections,
abbrev_offset,
&mut abbrevs,
&line_strings,
&strings,
)?;
// None should exist because we didn't give out any UnitId.
assert!(sections.debug_info_refs.is_empty());
assert!(sections.debug_loc_refs.is_empty());
assert!(sections.debug_loclists_refs.is_empty());
abbrevs.write(&mut sections.debug_abbrev)?;
Ok(())
}
}
#[cfg(feature = "read")]
pub(crate) mod convert {
use super::*;
use crate::read::{self, Reader};
use crate::write::{Address, ConvertResult};
impl Dwarf {
/// Create a `write::Dwarf` by converting a `read::Dwarf`.
///
/// `convert_address` is a function to convert read addresses into the `Address`
/// type. For non-relocatable addresses, this function may simply return
/// `Address::Constant(address)`. For relocatable addresses, it is the caller's
/// responsibility to determine the symbol and addend corresponding to the address
/// and return `Address::Symbol { symbol, addend }`.
pub fn from<R: Reader<Offset = usize>>(
dwarf: &read::Dwarf<R>,
convert_address: &dyn Fn(u64) -> Option<Address>,
) -> ConvertResult<Dwarf> {
let mut line_strings = LineStringTable::default();
let mut strings = StringTable::default();
let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?;
// TODO: convert the line programs that were not referenced by a unit.
let line_programs = Vec::new();
Ok(Dwarf {
units,
line_programs,
line_strings,
strings,
})
}
}
}

117
vendor/gimli/src/write/endian_vec.rs vendored Normal file
View File

@ -0,0 +1,117 @@
use alloc::vec::Vec;
use std::mem;
use crate::endianity::Endianity;
use crate::write::{Error, Result, Writer};
/// A `Vec<u8>` with endianity metadata.
///
/// This implements the `Writer` trait, which is used for all writing of DWARF sections.
#[derive(Debug, Clone)]
pub struct EndianVec<Endian>
where
Endian: Endianity,
{
vec: Vec<u8>,
endian: Endian,
}
impl<Endian> EndianVec<Endian>
where
Endian: Endianity,
{
/// Construct an empty `EndianVec` with the given endianity.
pub fn new(endian: Endian) -> EndianVec<Endian> {
EndianVec {
vec: Vec::new(),
endian,
}
}
/// Return a reference to the raw slice.
pub fn slice(&self) -> &[u8] {
&self.vec
}
/// Convert into a `Vec<u8>`.
pub fn into_vec(self) -> Vec<u8> {
self.vec
}
/// Take any written data out of the `EndianVec`, leaving an empty `Vec` in its place.
pub fn take(&mut self) -> Vec<u8> {
let mut vec = Vec::new();
mem::swap(&mut self.vec, &mut vec);
vec
}
}
impl<Endian> Writer for EndianVec<Endian>
where
Endian: Endianity,
{
type Endian = Endian;
#[inline]
fn endian(&self) -> Self::Endian {
self.endian
}
#[inline]
fn len(&self) -> usize {
self.vec.len()
}
fn write(&mut self, bytes: &[u8]) -> Result<()> {
self.vec.extend(bytes);
Ok(())
}
fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
if offset > self.vec.len() {
return Err(Error::OffsetOutOfBounds);
}
let to = &mut self.vec[offset..];
if bytes.len() > to.len() {
return Err(Error::LengthOutOfBounds);
}
let to = &mut to[..bytes.len()];
to.copy_from_slice(bytes);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::LittleEndian;
#[test]
fn test_endian_vec() {
let mut w = EndianVec::new(LittleEndian);
assert_eq!(w.endian(), LittleEndian);
assert_eq!(w.len(), 0);
w.write(&[1, 2]).unwrap();
assert_eq!(w.slice(), &[1, 2]);
assert_eq!(w.len(), 2);
w.write(&[3, 4, 5]).unwrap();
assert_eq!(w.slice(), &[1, 2, 3, 4, 5]);
assert_eq!(w.len(), 5);
w.write_at(0, &[6, 7]).unwrap();
assert_eq!(w.slice(), &[6, 7, 3, 4, 5]);
assert_eq!(w.len(), 5);
w.write_at(3, &[8, 9]).unwrap();
assert_eq!(w.slice(), &[6, 7, 3, 8, 9]);
assert_eq!(w.len(), 5);
assert_eq!(w.write_at(4, &[6, 7]), Err(Error::LengthOutOfBounds));
assert_eq!(w.write_at(5, &[6, 7]), Err(Error::LengthOutOfBounds));
assert_eq!(w.write_at(6, &[6, 7]), Err(Error::OffsetOutOfBounds));
assert_eq!(w.into_vec(), vec![6, 7, 3, 8, 9]);
}
}

1957
vendor/gimli/src/write/line.rs vendored Normal file

File diff suppressed because it is too large Load Diff

550
vendor/gimli/src/write/loc.rs vendored Normal file
View File

@ -0,0 +1,550 @@
use alloc::vec::Vec;
use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use crate::common::{Encoding, LocationListsOffset, SectionId};
use crate::write::{
Address, BaseId, DebugInfoReference, Error, Expression, Result, Section, Sections, UnitOffsets,
Writer,
};
define_section!(
DebugLoc,
LocationListsOffset,
"A writable `.debug_loc` section."
);
define_section!(
DebugLocLists,
LocationListsOffset,
"A writable `.debug_loclists` section."
);
define_offsets!(
LocationListOffsets: LocationListId => LocationListsOffset,
"The section offsets of a series of location lists within the `.debug_loc` or `.debug_loclists` sections."
);
define_id!(
LocationListId,
"An identifier for a location list in a `LocationListTable`."
);
/// A table of location lists that will be stored in a `.debug_loc` or `.debug_loclists` section.
#[derive(Debug, Default)]
pub struct LocationListTable {
base_id: BaseId,
locations: IndexSet<LocationList>,
}
impl LocationListTable {
/// Add a location list to the table.
pub fn add(&mut self, loc_list: LocationList) -> LocationListId {
let (index, _) = self.locations.insert_full(loc_list);
LocationListId::new(self.base_id, index)
}
/// Write the location list table to the appropriate section for the given DWARF version.
pub(crate) fn write<W: Writer>(
&self,
sections: &mut Sections<W>,
encoding: Encoding,
unit_offsets: Option<&UnitOffsets>,
) -> Result<LocationListOffsets> {
if self.locations.is_empty() {
return Ok(LocationListOffsets::none());
}
match encoding.version {
2..=4 => self.write_loc(
&mut sections.debug_loc,
&mut sections.debug_loc_refs,
encoding,
unit_offsets,
),
5 => self.write_loclists(
&mut sections.debug_loclists,
&mut sections.debug_loclists_refs,
encoding,
unit_offsets,
),
_ => Err(Error::UnsupportedVersion(encoding.version)),
}
}
/// Write the location list table to the `.debug_loc` section.
fn write_loc<W: Writer>(
&self,
w: &mut DebugLoc<W>,
refs: &mut Vec<DebugInfoReference>,
encoding: Encoding,
unit_offsets: Option<&UnitOffsets>,
) -> Result<LocationListOffsets> {
let address_size = encoding.address_size;
let mut offsets = Vec::new();
for loc_list in self.locations.iter() {
offsets.push(w.offset());
for loc in &loc_list.0 {
// Note that we must ensure none of the ranges have both begin == 0 and end == 0.
// We do this by ensuring that begin != end, which is a bit more restrictive
// than required, but still seems reasonable.
match *loc {
Location::BaseAddress { address } => {
let marker = !0 >> (64 - address_size * 8);
w.write_udata(marker, address_size)?;
w.write_address(address, address_size)?;
}
Location::OffsetPair {
begin,
end,
ref data,
} => {
if begin == end {
return Err(Error::InvalidRange);
}
w.write_udata(begin, address_size)?;
w.write_udata(end, address_size)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::StartEnd {
begin,
end,
ref data,
} => {
if begin == end {
return Err(Error::InvalidRange);
}
w.write_address(begin, address_size)?;
w.write_address(end, address_size)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::StartLength {
begin,
length,
ref data,
} => {
let end = match begin {
Address::Constant(begin) => Address::Constant(begin + length),
Address::Symbol { symbol, addend } => Address::Symbol {
symbol,
addend: addend + length as i64,
},
};
if begin == end {
return Err(Error::InvalidRange);
}
w.write_address(begin, address_size)?;
w.write_address(end, address_size)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::DefaultLocation { .. } => {
return Err(Error::InvalidRange);
}
}
}
w.write_udata(0, address_size)?;
w.write_udata(0, address_size)?;
}
Ok(LocationListOffsets {
base_id: self.base_id,
offsets,
})
}
/// Write the location list table to the `.debug_loclists` section.
fn write_loclists<W: Writer>(
&self,
w: &mut DebugLocLists<W>,
refs: &mut Vec<DebugInfoReference>,
encoding: Encoding,
unit_offsets: Option<&UnitOffsets>,
) -> Result<LocationListOffsets> {
let mut offsets = Vec::new();
if encoding.version != 5 {
return Err(Error::NeedVersion(5));
}
let length_offset = w.write_initial_length(encoding.format)?;
let length_base = w.len();
w.write_u16(encoding.version)?;
w.write_u8(encoding.address_size)?;
w.write_u8(0)?; // segment_selector_size
w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28)
// FIXME implement DW_FORM_rnglistx writing and implement the offset entry list
for loc_list in self.locations.iter() {
offsets.push(w.offset());
for loc in &loc_list.0 {
match *loc {
Location::BaseAddress { address } => {
w.write_u8(crate::constants::DW_LLE_base_address.0)?;
w.write_address(address, encoding.address_size)?;
}
Location::OffsetPair {
begin,
end,
ref data,
} => {
w.write_u8(crate::constants::DW_LLE_offset_pair.0)?;
w.write_uleb128(begin)?;
w.write_uleb128(end)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::StartEnd {
begin,
end,
ref data,
} => {
w.write_u8(crate::constants::DW_LLE_start_end.0)?;
w.write_address(begin, encoding.address_size)?;
w.write_address(end, encoding.address_size)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::StartLength {
begin,
length,
ref data,
} => {
w.write_u8(crate::constants::DW_LLE_start_length.0)?;
w.write_address(begin, encoding.address_size)?;
w.write_uleb128(length)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
Location::DefaultLocation { ref data } => {
w.write_u8(crate::constants::DW_LLE_default_location.0)?;
write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
}
}
}
w.write_u8(crate::constants::DW_LLE_end_of_list.0)?;
}
let length = (w.len() - length_base) as u64;
w.write_initial_length_at(length_offset, length, encoding.format)?;
Ok(LocationListOffsets {
base_id: self.base_id,
offsets,
})
}
}
/// A locations list that will be stored in a `.debug_loc` or `.debug_loclists` section.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct LocationList(pub Vec<Location>);
/// A single location.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Location {
/// DW_LLE_base_address
BaseAddress {
/// Base address.
address: Address,
},
/// DW_LLE_offset_pair
OffsetPair {
/// Start of range relative to base address.
begin: u64,
/// End of range relative to base address.
end: u64,
/// Location description.
data: Expression,
},
/// DW_LLE_start_end
StartEnd {
/// Start of range.
begin: Address,
/// End of range.
end: Address,
/// Location description.
data: Expression,
},
/// DW_LLE_start_length
StartLength {
/// Start of range.
begin: Address,
/// Length of range.
length: u64,
/// Location description.
data: Expression,
},
/// DW_LLE_default_location
DefaultLocation {
/// Location description.
data: Expression,
},
}
fn write_expression<W: Writer>(
w: &mut W,
refs: &mut Vec<DebugInfoReference>,
encoding: Encoding,
unit_offsets: Option<&UnitOffsets>,
val: &Expression,
) -> Result<()> {
let size = val.size(encoding, unit_offsets) as u64;
if encoding.version <= 4 {
w.write_udata(size, 2)?;
} else {
w.write_uleb128(size)?;
}
val.write(w, Some(refs), encoding, unit_offsets)?;
Ok(())
}
#[cfg(feature = "read")]
mod convert {
use super::*;
use crate::read::{self, Reader};
use crate::write::{ConvertError, ConvertResult, ConvertUnitContext};
impl LocationList {
/// Create a location list by reading the data from the give location list iter.
pub(crate) fn from<R: Reader<Offset = usize>>(
mut from: read::RawLocListIter<R>,
context: &ConvertUnitContext<R>,
) -> ConvertResult<Self> {
let mut have_base_address = context.base_address != Address::Constant(0);
let convert_address =
|x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress);
let convert_expression = |x| {
Expression::from(
x,
context.unit.encoding(),
Some(context.dwarf),
Some(context.unit),
Some(context.entry_ids),
context.convert_address,
)
};
let mut loc_list = Vec::new();
while let Some(from_loc) = from.next()? {
let loc = match from_loc {
read::RawLocListEntry::AddressOrOffsetPair { begin, end, data } => {
// These were parsed as addresses, even if they are offsets.
let begin = convert_address(begin)?;
let end = convert_address(end)?;
let data = convert_expression(data)?;
match (begin, end) {
(Address::Constant(begin_offset), Address::Constant(end_offset)) => {
if have_base_address {
Location::OffsetPair {
begin: begin_offset,
end: end_offset,
data,
}
} else {
Location::StartEnd { begin, end, data }
}
}
_ => {
if have_base_address {
// At least one of begin/end is an address, but we also have
// a base address. Adding addresses is undefined.
return Err(ConvertError::InvalidRangeRelativeAddress);
}
Location::StartEnd { begin, end, data }
}
}
}
read::RawLocListEntry::BaseAddress { addr } => {
have_base_address = true;
let address = convert_address(addr)?;
Location::BaseAddress { address }
}
read::RawLocListEntry::BaseAddressx { addr } => {
have_base_address = true;
let address = convert_address(context.dwarf.address(context.unit, addr)?)?;
Location::BaseAddress { address }
}
read::RawLocListEntry::StartxEndx { begin, end, data } => {
let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
let end = convert_address(context.dwarf.address(context.unit, end)?)?;
let data = convert_expression(data)?;
Location::StartEnd { begin, end, data }
}
read::RawLocListEntry::StartxLength {
begin,
length,
data,
} => {
let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
let data = convert_expression(data)?;
Location::StartLength {
begin,
length,
data,
}
}
read::RawLocListEntry::OffsetPair { begin, end, data } => {
let data = convert_expression(data)?;
Location::OffsetPair { begin, end, data }
}
read::RawLocListEntry::StartEnd { begin, end, data } => {
let begin = convert_address(begin)?;
let end = convert_address(end)?;
let data = convert_expression(data)?;
Location::StartEnd { begin, end, data }
}
read::RawLocListEntry::StartLength {
begin,
length,
data,
} => {
let begin = convert_address(begin)?;
let data = convert_expression(data)?;
Location::StartLength {
begin,
length,
data,
}
}
read::RawLocListEntry::DefaultLocation { data } => {
let data = convert_expression(data)?;
Location::DefaultLocation { data }
}
};
// In some cases, existing data may contain begin == end, filtering
// these out.
match loc {
Location::StartLength { length, .. } if length == 0 => continue,
Location::StartEnd { begin, end, .. } if begin == end => continue,
Location::OffsetPair { begin, end, .. } if begin == end => continue,
_ => (),
}
loc_list.push(loc);
}
Ok(LocationList(loc_list))
}
}
}
#[cfg(test)]
#[cfg(feature = "read")]
mod tests {
use super::*;
use crate::common::{
DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase,
DebugStrOffsetsBase, Format,
};
use crate::read;
use crate::write::{
ConvertUnitContext, EndianVec, LineStringTable, RangeListTable, StringTable,
};
use crate::LittleEndian;
use std::collections::HashMap;
use std::sync::Arc;
#[test]
fn test_loc_list() {
let mut line_strings = LineStringTable::default();
let mut strings = StringTable::default();
let mut expression = Expression::new();
expression.op_constu(0);
for &version in &[2, 3, 4, 5] {
for &address_size in &[4, 8] {
for &format in &[Format::Dwarf32, Format::Dwarf64] {
let encoding = Encoding {
format,
version,
address_size,
};
let mut loc_list = LocationList(vec![
Location::StartLength {
begin: Address::Constant(6666),
length: 7777,
data: expression.clone(),
},
Location::StartEnd {
begin: Address::Constant(4444),
end: Address::Constant(5555),
data: expression.clone(),
},
Location::BaseAddress {
address: Address::Constant(1111),
},
Location::OffsetPair {
begin: 2222,
end: 3333,
data: expression.clone(),
},
]);
if version >= 5 {
loc_list.0.push(Location::DefaultLocation {
data: expression.clone(),
});
}
let mut locations = LocationListTable::default();
let loc_list_id = locations.add(loc_list.clone());
let mut sections = Sections::new(EndianVec::new(LittleEndian));
let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap();
assert!(sections.debug_loc_refs.is_empty());
assert!(sections.debug_loclists_refs.is_empty());
let read_debug_loc =
read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian);
let read_debug_loclists =
read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian);
let read_loc = read::LocationLists::new(read_debug_loc, read_debug_loclists);
let offset = loc_list_offsets.get(loc_list_id);
let read_loc_list = read_loc.raw_locations(offset, encoding).unwrap();
let dwarf = read::Dwarf {
locations: read_loc,
..Default::default()
};
let unit = read::Unit {
header: read::UnitHeader::new(
encoding,
0,
read::UnitType::Compilation,
DebugAbbrevOffset(0),
DebugInfoOffset(0).into(),
read::EndianSlice::default(),
),
abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
str_offsets_base: DebugStrOffsetsBase(0),
addr_base: DebugAddrBase(0),
loclists_base: DebugLocListsBase(0),
rnglists_base: DebugRngListsBase(0),
line_program: None,
dwo_id: None,
};
let context = ConvertUnitContext {
dwarf: &dwarf,
unit: &unit,
line_strings: &mut line_strings,
strings: &mut strings,
ranges: &mut RangeListTable::default(),
locations: &mut locations,
convert_address: &|address| Some(Address::Constant(address)),
base_address: Address::Constant(0),
line_program_offset: None,
line_program_files: Vec::new(),
entry_ids: &HashMap::new(),
};
let convert_loc_list = LocationList::from(read_loc_list, &context).unwrap();
if version <= 4 {
loc_list.0[0] = Location::StartEnd {
begin: Address::Constant(6666),
end: Address::Constant(6666 + 7777),
data: expression.clone(),
};
}
assert_eq!(loc_list, convert_loc_list);
}
}
}
}
}

425
vendor/gimli/src/write/mod.rs vendored Normal file
View File

@ -0,0 +1,425 @@
//! Write DWARF debugging information.
//!
//! ## API Structure
//!
//! This module works by building up a representation of the debugging information
//! in memory, and then writing it all at once. It supports two major use cases:
//!
//! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF
//! for a single compilation unit.
//!
//! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple
//! compilation units.
//!
//! The module also supports reading in DWARF debugging information and writing it out
//! again, possibly after modifying it. Create a [`read::Dwarf`](../read/struct.Dwarf.html)
//! instance, and then use [`Dwarf::from`](./struct.Dwarf.html#method.from) to convert
//! it to a writable instance.
//!
//! ## Example Usage
//!
//! Write a compilation unit containing only the top level DIE.
//!
//! ```rust
//! use gimli::write::{
//! Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections,
//! };
//!
//! fn example() -> Result<(), Error> {
//! // Choose the encoding parameters.
//! let encoding = gimli::Encoding {
//! format: gimli::Format::Dwarf32,
//! version: 5,
//! address_size: 8,
//! };
//! // Create a container for a single compilation unit.
//! let mut dwarf = DwarfUnit::new(encoding);
//! // Set a range attribute on the root DIE.
//! let range_list = RangeList(vec![Range::StartLength {
//! begin: Address::Constant(0x100),
//! length: 42,
//! }]);
//! let range_list_id = dwarf.unit.ranges.add(range_list);
//! let root = dwarf.unit.root();
//! dwarf.unit.get_mut(root).set(
//! gimli::DW_AT_ranges,
//! AttributeValue::RangeListRef(range_list_id),
//! );
//! // Create a `Vec` for each DWARF section.
//! let mut sections = Sections::new(EndianVec::new(gimli::LittleEndian));
//! // Finally, write the DWARF data to the sections.
//! dwarf.write(&mut sections)?;
//! sections.for_each(|id, data| {
//! // Here you can add the data to the output object file.
//! Ok(())
//! })
//! }
//! # fn main() {
//! # example().unwrap();
//! # }
use std::error;
use std::fmt;
use std::result;
use crate::constants;
mod endian_vec;
pub use self::endian_vec::*;
mod writer;
pub use self::writer::*;
#[macro_use]
mod section;
pub use self::section::*;
macro_rules! define_id {
($name:ident, $docs:expr) => {
#[doc=$docs]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct $name {
base_id: BaseId,
index: usize,
}
impl $name {
#[inline]
fn new(base_id: BaseId, index: usize) -> Self {
$name { base_id, index }
}
}
};
}
macro_rules! define_offsets {
($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => {
#[doc=$off_doc]
#[derive(Debug)]
pub struct $offsets {
base_id: BaseId,
// We know ids start at 0.
offsets: Vec<$offset>,
}
impl $offsets {
/// Return an empty list of offsets.
#[inline]
pub fn none() -> Self {
$offsets {
base_id: BaseId::default(),
offsets: Vec::new(),
}
}
/// Get the offset
///
/// # Panics
///
/// Panics if `id` is invalid.
#[inline]
pub fn get(&self, id: $id) -> $offset {
debug_assert_eq!(self.base_id, id.base_id);
self.offsets[id.index]
}
/// Return the number of offsets.
#[inline]
pub fn count(&self) -> usize {
self.offsets.len()
}
}
};
}
mod abbrev;
pub use self::abbrev::*;
mod cfi;
pub use self::cfi::*;
mod dwarf;
pub use self::dwarf::*;
mod line;
pub use self::line::*;
mod loc;
pub use self::loc::*;
mod op;
pub use self::op::*;
mod range;
pub use self::range::*;
mod str;
pub use self::str::*;
mod unit;
pub use self::unit::*;
/// An error that occurred when writing.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Error {
/// The given offset is out of bounds.
OffsetOutOfBounds,
/// The given length is out of bounds.
LengthOutOfBounds,
/// The attribute value is an invalid for writing.
InvalidAttributeValue,
/// The value is too large for the encoding form.
ValueTooLarge,
/// Unsupported word size.
UnsupportedWordSize(u8),
/// Unsupported DWARF version.
UnsupportedVersion(u16),
/// The unit length is too large for the requested DWARF format.
InitialLengthOverflow,
/// The address is invalid.
InvalidAddress,
/// The reference is invalid.
InvalidReference,
/// A requested feature requires a different DWARF version.
NeedVersion(u16),
/// Strings in line number program have mismatched forms.
LineStringFormMismatch,
/// The range is empty or otherwise invalid.
InvalidRange,
/// The line number program encoding is incompatible with the unit encoding.
IncompatibleLineProgramEncoding,
/// Could not encode code offset for a frame instruction.
InvalidFrameCodeOffset(u32),
/// Could not encode data offset for a frame instruction.
InvalidFrameDataOffset(i32),
/// Unsupported eh_frame pointer encoding.
UnsupportedPointerEncoding(constants::DwEhPe),
/// Unsupported reference in CFI expression.
UnsupportedCfiExpressionReference,
/// Unsupported forward reference in expression.
UnsupportedExpressionForwardReference,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
Error::OffsetOutOfBounds => write!(f, "The given offset is out of bounds."),
Error::LengthOutOfBounds => write!(f, "The given length is out of bounds."),
Error::InvalidAttributeValue => {
write!(f, "The attribute value is an invalid for writing.")
}
Error::ValueTooLarge => write!(f, "The value is too large for the encoding form."),
Error::UnsupportedWordSize(size) => write!(f, "Unsupported word size: {}", size),
Error::UnsupportedVersion(version) => {
write!(f, "Unsupported DWARF version: {}", version)
}
Error::InitialLengthOverflow => write!(
f,
"The unit length is too large for the requested DWARF format."
),
Error::InvalidAddress => write!(f, "The address is invalid."),
Error::InvalidReference => write!(f, "The reference is invalid."),
Error::NeedVersion(version) => write!(
f,
"A requested feature requires a DWARF version {}.",
version
),
Error::LineStringFormMismatch => {
write!(f, "Strings in line number program have mismatched forms.")
}
Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."),
Error::IncompatibleLineProgramEncoding => write!(
f,
"The line number program encoding is incompatible with the unit encoding."
),
Error::InvalidFrameCodeOffset(offset) => write!(
f,
"Could not encode code offset ({}) for a frame instruction.",
offset,
),
Error::InvalidFrameDataOffset(offset) => write!(
f,
"Could not encode data offset ({}) for a frame instruction.",
offset,
),
Error::UnsupportedPointerEncoding(eh_pe) => {
write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe)
}
Error::UnsupportedCfiExpressionReference => {
write!(f, "Unsupported reference in CFI expression.")
}
Error::UnsupportedExpressionForwardReference => {
write!(f, "Unsupported forward reference in expression.")
}
}
}
}
impl error::Error for Error {}
/// The result of a write.
pub type Result<T> = result::Result<T, Error>;
/// An address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Address {
/// A fixed address that does not require relocation.
Constant(u64),
/// An address that is relative to a symbol which may be relocated.
Symbol {
/// The symbol that the address is relative to.
///
/// The meaning of this value is decided by the writer, but
/// will typically be an index into a symbol table.
symbol: usize,
/// The offset of the address relative to the symbol.
///
/// This will typically be used as the addend in a relocation.
addend: i64,
},
}
/// A reference to a `.debug_info` entry.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Reference {
/// An external symbol.
///
/// The meaning of this value is decided by the writer, but
/// will typically be an index into a symbol table.
Symbol(usize),
/// An entry in the same section.
///
/// This only supports references in units that are emitted together.
Entry(UnitId, UnitEntryId),
}
// This type is only used in debug assertions.
#[cfg(not(debug_assertions))]
type BaseId = ();
#[cfg(debug_assertions)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct BaseId(usize);
#[cfg(debug_assertions)]
impl Default for BaseId {
fn default() -> Self {
use std::sync::atomic;
static BASE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
BaseId(BASE_ID.fetch_add(1, atomic::Ordering::Relaxed))
}
}
#[cfg(feature = "read")]
mod convert {
use super::*;
use crate::read;
pub(crate) use super::unit::convert::*;
/// An error that occurred when converting a read value into a write value.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConvertError {
/// An error occurred when reading.
Read(read::Error),
/// Writing of this attribute value is not implemented yet.
UnsupportedAttributeValue,
/// This attribute value is an invalid name/form combination.
InvalidAttributeValue,
/// A `.debug_info` reference does not refer to a valid entry.
InvalidDebugInfoOffset,
/// An address could not be converted.
InvalidAddress,
/// Writing this line number instruction is not implemented yet.
UnsupportedLineInstruction,
/// Writing this form of line string is not implemented yet.
UnsupportedLineStringForm,
/// A `.debug_line` file index is invalid.
InvalidFileIndex,
/// A `.debug_line` directory index is invalid.
InvalidDirectoryIndex,
/// A `.debug_line` line base is invalid.
InvalidLineBase,
/// A `.debug_line` reference is invalid.
InvalidLineRef,
/// A `.debug_info` unit entry reference is invalid.
InvalidUnitRef,
/// A `.debug_info` reference is invalid.
InvalidDebugInfoRef,
/// Invalid relative address in a range list.
InvalidRangeRelativeAddress,
/// Writing this CFI instruction is not implemented yet.
UnsupportedCfiInstruction,
/// Writing indirect pointers is not implemented yet.
UnsupportedIndirectAddress,
/// Writing this expression operation is not implemented yet.
UnsupportedOperation,
/// Operation branch target is invalid.
InvalidBranchTarget,
/// Writing this unit type is not supported yet.
UnsupportedUnitType,
}
impl fmt::Display for ConvertError {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
use self::ConvertError::*;
match *self {
Read(ref e) => e.fmt(f),
UnsupportedAttributeValue => {
write!(f, "Writing of this attribute value is not implemented yet.")
}
InvalidAttributeValue => write!(
f,
"This attribute value is an invalid name/form combination."
),
InvalidDebugInfoOffset => write!(
f,
"A `.debug_info` reference does not refer to a valid entry."
),
InvalidAddress => write!(f, "An address could not be converted."),
UnsupportedLineInstruction => write!(
f,
"Writing this line number instruction is not implemented yet."
),
UnsupportedLineStringForm => write!(
f,
"Writing this form of line string is not implemented yet."
),
InvalidFileIndex => write!(f, "A `.debug_line` file index is invalid."),
InvalidDirectoryIndex => write!(f, "A `.debug_line` directory index is invalid."),
InvalidLineBase => write!(f, "A `.debug_line` line base is invalid."),
InvalidLineRef => write!(f, "A `.debug_line` reference is invalid."),
InvalidUnitRef => write!(f, "A `.debug_info` unit entry reference is invalid."),
InvalidDebugInfoRef => write!(f, "A `.debug_info` reference is invalid."),
InvalidRangeRelativeAddress => {
write!(f, "Invalid relative address in a range list.")
}
UnsupportedCfiInstruction => {
write!(f, "Writing this CFI instruction is not implemented yet.")
}
UnsupportedIndirectAddress => {
write!(f, "Writing indirect pointers is not implemented yet.")
}
UnsupportedOperation => write!(
f,
"Writing this expression operation is not implemented yet."
),
InvalidBranchTarget => write!(f, "Operation branch target is invalid."),
UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."),
}
}
}
impl error::Error for ConvertError {}
impl From<read::Error> for ConvertError {
fn from(e: read::Error) -> Self {
ConvertError::Read(e)
}
}
/// The result of a conversion.
pub type ConvertResult<T> = result::Result<T, ConvertError>;
}
#[cfg(feature = "read")]
pub use self::convert::*;

1618
vendor/gimli/src/write/op.rs vendored Normal file

File diff suppressed because it is too large Load Diff

416
vendor/gimli/src/write/range.rs vendored Normal file
View File

@ -0,0 +1,416 @@
use alloc::vec::Vec;
use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use crate::common::{Encoding, RangeListsOffset, SectionId};
use crate::write::{Address, BaseId, Error, Result, Section, Sections, Writer};
define_section!(
DebugRanges,
RangeListsOffset,
"A writable `.debug_ranges` section."
);
define_section!(
DebugRngLists,
RangeListsOffset,
"A writable `.debug_rnglists` section."
);
define_offsets!(
RangeListOffsets: RangeListId => RangeListsOffset,
"The section offsets of a series of range lists within the `.debug_ranges` or `.debug_rnglists` sections."
);
define_id!(
RangeListId,
"An identifier for a range list in a `RangeListTable`."
);
/// A table of range lists that will be stored in a `.debug_ranges` or `.debug_rnglists` section.
#[derive(Debug, Default)]
pub struct RangeListTable {
base_id: BaseId,
ranges: IndexSet<RangeList>,
}
impl RangeListTable {
/// Add a range list to the table.
pub fn add(&mut self, range_list: RangeList) -> RangeListId {
let (index, _) = self.ranges.insert_full(range_list);
RangeListId::new(self.base_id, index)
}
/// Write the range list table to the appropriate section for the given DWARF version.
pub(crate) fn write<W: Writer>(
&self,
sections: &mut Sections<W>,
encoding: Encoding,
) -> Result<RangeListOffsets> {
if self.ranges.is_empty() {
return Ok(RangeListOffsets::none());
}
match encoding.version {
2..=4 => self.write_ranges(&mut sections.debug_ranges, encoding.address_size),
5 => self.write_rnglists(&mut sections.debug_rnglists, encoding),
_ => Err(Error::UnsupportedVersion(encoding.version)),
}
}
/// Write the range list table to the `.debug_ranges` section.
fn write_ranges<W: Writer>(
&self,
w: &mut DebugRanges<W>,
address_size: u8,
) -> Result<RangeListOffsets> {
let mut offsets = Vec::new();
for range_list in self.ranges.iter() {
offsets.push(w.offset());
for range in &range_list.0 {
// Note that we must ensure none of the ranges have both begin == 0 and end == 0.
// We do this by ensuring that begin != end, which is a bit more restrictive
// than required, but still seems reasonable.
match *range {
Range::BaseAddress { address } => {
let marker = !0 >> (64 - address_size * 8);
w.write_udata(marker, address_size)?;
w.write_address(address, address_size)?;
}
Range::OffsetPair { begin, end } => {
if begin == end {
return Err(Error::InvalidRange);
}
w.write_udata(begin, address_size)?;
w.write_udata(end, address_size)?;
}
Range::StartEnd { begin, end } => {
if begin == end {
return Err(Error::InvalidRange);
}
w.write_address(begin, address_size)?;
w.write_address(end, address_size)?;
}
Range::StartLength { begin, length } => {
let end = match begin {
Address::Constant(begin) => Address::Constant(begin + length),
Address::Symbol { symbol, addend } => Address::Symbol {
symbol,
addend: addend + length as i64,
},
};
if begin == end {
return Err(Error::InvalidRange);
}
w.write_address(begin, address_size)?;
w.write_address(end, address_size)?;
}
}
}
w.write_udata(0, address_size)?;
w.write_udata(0, address_size)?;
}
Ok(RangeListOffsets {
base_id: self.base_id,
offsets,
})
}
/// Write the range list table to the `.debug_rnglists` section.
fn write_rnglists<W: Writer>(
&self,
w: &mut DebugRngLists<W>,
encoding: Encoding,
) -> Result<RangeListOffsets> {
let mut offsets = Vec::new();
if encoding.version != 5 {
return Err(Error::NeedVersion(5));
}
let length_offset = w.write_initial_length(encoding.format)?;
let length_base = w.len();
w.write_u16(encoding.version)?;
w.write_u8(encoding.address_size)?;
w.write_u8(0)?; // segment_selector_size
w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28)
// FIXME implement DW_FORM_rnglistx writing and implement the offset entry list
for range_list in self.ranges.iter() {
offsets.push(w.offset());
for range in &range_list.0 {
match *range {
Range::BaseAddress { address } => {
w.write_u8(crate::constants::DW_RLE_base_address.0)?;
w.write_address(address, encoding.address_size)?;
}
Range::OffsetPair { begin, end } => {
w.write_u8(crate::constants::DW_RLE_offset_pair.0)?;
w.write_uleb128(begin)?;
w.write_uleb128(end)?;
}
Range::StartEnd { begin, end } => {
w.write_u8(crate::constants::DW_RLE_start_end.0)?;
w.write_address(begin, encoding.address_size)?;
w.write_address(end, encoding.address_size)?;
}
Range::StartLength { begin, length } => {
w.write_u8(crate::constants::DW_RLE_start_length.0)?;
w.write_address(begin, encoding.address_size)?;
w.write_uleb128(length)?;
}
}
}
w.write_u8(crate::constants::DW_RLE_end_of_list.0)?;
}
let length = (w.len() - length_base) as u64;
w.write_initial_length_at(length_offset, length, encoding.format)?;
Ok(RangeListOffsets {
base_id: self.base_id,
offsets,
})
}
}
/// A range list that will be stored in a `.debug_ranges` or `.debug_rnglists` section.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct RangeList(pub Vec<Range>);
/// A single range.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Range {
/// DW_RLE_base_address
BaseAddress {
/// Base address.
address: Address,
},
/// DW_RLE_offset_pair
OffsetPair {
/// Start of range relative to base address.
begin: u64,
/// End of range relative to base address.
end: u64,
},
/// DW_RLE_start_end
StartEnd {
/// Start of range.
begin: Address,
/// End of range.
end: Address,
},
/// DW_RLE_start_length
StartLength {
/// Start of range.
begin: Address,
/// Length of range.
length: u64,
},
}
#[cfg(feature = "read")]
mod convert {
use super::*;
use crate::read::{self, Reader};
use crate::write::{ConvertError, ConvertResult, ConvertUnitContext};
impl RangeList {
/// Create a range list by reading the data from the give range list iter.
pub(crate) fn from<R: Reader<Offset = usize>>(
mut from: read::RawRngListIter<R>,
context: &ConvertUnitContext<R>,
) -> ConvertResult<Self> {
let mut have_base_address = context.base_address != Address::Constant(0);
let convert_address =
|x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress);
let mut ranges = Vec::new();
while let Some(from_range) = from.next()? {
let range = match from_range {
read::RawRngListEntry::AddressOrOffsetPair { begin, end } => {
// These were parsed as addresses, even if they are offsets.
let begin = convert_address(begin)?;
let end = convert_address(end)?;
match (begin, end) {
(Address::Constant(begin_offset), Address::Constant(end_offset)) => {
if have_base_address {
Range::OffsetPair {
begin: begin_offset,
end: end_offset,
}
} else {
Range::StartEnd { begin, end }
}
}
_ => {
if have_base_address {
// At least one of begin/end is an address, but we also have
// a base address. Adding addresses is undefined.
return Err(ConvertError::InvalidRangeRelativeAddress);
}
Range::StartEnd { begin, end }
}
}
}
read::RawRngListEntry::BaseAddress { addr } => {
have_base_address = true;
let address = convert_address(addr)?;
Range::BaseAddress { address }
}
read::RawRngListEntry::BaseAddressx { addr } => {
have_base_address = true;
let address = convert_address(context.dwarf.address(context.unit, addr)?)?;
Range::BaseAddress { address }
}
read::RawRngListEntry::StartxEndx { begin, end } => {
let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
let end = convert_address(context.dwarf.address(context.unit, end)?)?;
Range::StartEnd { begin, end }
}
read::RawRngListEntry::StartxLength { begin, length } => {
let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
Range::StartLength { begin, length }
}
read::RawRngListEntry::OffsetPair { begin, end } => {
Range::OffsetPair { begin, end }
}
read::RawRngListEntry::StartEnd { begin, end } => {
let begin = convert_address(begin)?;
let end = convert_address(end)?;
Range::StartEnd { begin, end }
}
read::RawRngListEntry::StartLength { begin, length } => {
let begin = convert_address(begin)?;
Range::StartLength { begin, length }
}
};
// Filtering empty ranges out.
match range {
Range::StartLength { length, .. } if length == 0 => continue,
Range::StartEnd { begin, end, .. } if begin == end => continue,
Range::OffsetPair { begin, end, .. } if begin == end => continue,
_ => (),
}
ranges.push(range);
}
Ok(RangeList(ranges))
}
}
}
#[cfg(test)]
#[cfg(feature = "read")]
mod tests {
use super::*;
use crate::common::{
DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase,
DebugStrOffsetsBase, Format,
};
use crate::read;
use crate::write::{
ConvertUnitContext, EndianVec, LineStringTable, LocationListTable, Range, RangeListTable,
StringTable,
};
use crate::LittleEndian;
use std::collections::HashMap;
use std::sync::Arc;
#[test]
fn test_range() {
let mut line_strings = LineStringTable::default();
let mut strings = StringTable::default();
for &version in &[2, 3, 4, 5] {
for &address_size in &[4, 8] {
for &format in &[Format::Dwarf32, Format::Dwarf64] {
let encoding = Encoding {
format,
version,
address_size,
};
let mut range_list = RangeList(vec![
Range::StartLength {
begin: Address::Constant(6666),
length: 7777,
},
Range::StartEnd {
begin: Address::Constant(4444),
end: Address::Constant(5555),
},
Range::BaseAddress {
address: Address::Constant(1111),
},
Range::OffsetPair {
begin: 2222,
end: 3333,
},
]);
let mut ranges = RangeListTable::default();
let range_list_id = ranges.add(range_list.clone());
let mut sections = Sections::new(EndianVec::new(LittleEndian));
let range_list_offsets = ranges.write(&mut sections, encoding).unwrap();
let read_debug_ranges =
read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian);
let read_debug_rnglists =
read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian);
let read_ranges = read::RangeLists::new(read_debug_ranges, read_debug_rnglists);
let offset = range_list_offsets.get(range_list_id);
let read_range_list = read_ranges.raw_ranges(offset, encoding).unwrap();
let dwarf = read::Dwarf {
ranges: read_ranges,
..Default::default()
};
let unit = read::Unit {
header: read::UnitHeader::new(
encoding,
0,
read::UnitType::Compilation,
DebugAbbrevOffset(0),
DebugInfoOffset(0).into(),
read::EndianSlice::default(),
),
abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
str_offsets_base: DebugStrOffsetsBase(0),
addr_base: DebugAddrBase(0),
loclists_base: DebugLocListsBase(0),
rnglists_base: DebugRngListsBase(0),
line_program: None,
dwo_id: None,
};
let context = ConvertUnitContext {
dwarf: &dwarf,
unit: &unit,
line_strings: &mut line_strings,
strings: &mut strings,
ranges: &mut ranges,
locations: &mut LocationListTable::default(),
convert_address: &|address| Some(Address::Constant(address)),
base_address: Address::Constant(0),
line_program_offset: None,
line_program_files: Vec::new(),
entry_ids: &HashMap::new(),
};
let convert_range_list = RangeList::from(read_range_list, &context).unwrap();
if version <= 4 {
range_list.0[0] = Range::StartEnd {
begin: Address::Constant(6666),
end: Address::Constant(6666 + 7777),
};
}
assert_eq!(range_list, convert_range_list);
}
}
}
}
}

172
vendor/gimli/src/write/section.rs vendored Normal file
View File

@ -0,0 +1,172 @@
use std::ops::DerefMut;
use std::result;
use std::vec::Vec;
use crate::common::SectionId;
use crate::write::{
DebugAbbrev, DebugFrame, DebugInfo, DebugInfoReference, DebugLine, DebugLineStr, DebugLoc,
DebugLocLists, DebugRanges, DebugRngLists, DebugStr, EhFrame, Writer,
};
macro_rules! define_section {
($name:ident, $offset:ident, $docs:expr) => {
#[doc=$docs]
#[derive(Debug, Default)]
pub struct $name<W: Writer>(pub W);
impl<W: Writer> $name<W> {
/// Return the offset of the next write.
pub fn offset(&self) -> $offset {
$offset(self.len())
}
}
impl<W: Writer> From<W> for $name<W> {
#[inline]
fn from(w: W) -> Self {
$name(w)
}
}
impl<W: Writer> Deref for $name<W> {
type Target = W;
#[inline]
fn deref(&self) -> &W {
&self.0
}
}
impl<W: Writer> DerefMut for $name<W> {
#[inline]
fn deref_mut(&mut self) -> &mut W {
&mut self.0
}
}
impl<W: Writer> Section<W> for $name<W> {
#[inline]
fn id(&self) -> SectionId {
SectionId::$name
}
}
};
}
/// Functionality common to all writable DWARF sections.
pub trait Section<W: Writer>: DerefMut<Target = W> {
/// Returns the DWARF section kind for this type.
fn id(&self) -> SectionId;
/// Returns the ELF section name for this type.
fn name(&self) -> &'static str {
self.id().name()
}
}
/// All of the writable DWARF sections.
#[derive(Debug, Default)]
pub struct Sections<W: Writer> {
/// The `.debug_abbrev` section.
pub debug_abbrev: DebugAbbrev<W>,
/// The `.debug_info` section.
pub debug_info: DebugInfo<W>,
/// The `.debug_line` section.
pub debug_line: DebugLine<W>,
/// The `.debug_line_str` section.
pub debug_line_str: DebugLineStr<W>,
/// The `.debug_ranges` section.
pub debug_ranges: DebugRanges<W>,
/// The `.debug_rnglists` section.
pub debug_rnglists: DebugRngLists<W>,
/// The `.debug_loc` section.
pub debug_loc: DebugLoc<W>,
/// The `.debug_loclists` section.
pub debug_loclists: DebugLocLists<W>,
/// The `.debug_str` section.
pub debug_str: DebugStr<W>,
/// The `.debug_frame` section.
pub debug_frame: DebugFrame<W>,
/// The `.eh_frame` section.
pub eh_frame: EhFrame<W>,
/// Unresolved references in the `.debug_info` section.
pub(crate) debug_info_refs: Vec<DebugInfoReference>,
/// Unresolved references in the `.debug_loc` section.
pub(crate) debug_loc_refs: Vec<DebugInfoReference>,
/// Unresolved references in the `.debug_loclists` section.
pub(crate) debug_loclists_refs: Vec<DebugInfoReference>,
}
impl<W: Writer + Clone> Sections<W> {
/// Create a new `Sections` using clones of the given `section`.
pub fn new(section: W) -> Self {
Sections {
debug_abbrev: DebugAbbrev(section.clone()),
debug_info: DebugInfo(section.clone()),
debug_line: DebugLine(section.clone()),
debug_line_str: DebugLineStr(section.clone()),
debug_ranges: DebugRanges(section.clone()),
debug_rnglists: DebugRngLists(section.clone()),
debug_loc: DebugLoc(section.clone()),
debug_loclists: DebugLocLists(section.clone()),
debug_str: DebugStr(section.clone()),
debug_frame: DebugFrame(section.clone()),
eh_frame: EhFrame(section),
debug_info_refs: Vec::new(),
debug_loc_refs: Vec::new(),
debug_loclists_refs: Vec::new(),
}
}
}
impl<W: Writer> Sections<W> {
/// For each section, call `f` once with a shared reference.
pub fn for_each<F, E>(&self, mut f: F) -> result::Result<(), E>
where
F: FnMut(SectionId, &W) -> result::Result<(), E>,
{
macro_rules! f {
($s:expr) => {
f($s.id(), &$s)
};
}
// Ordered so that earlier sections do not reference later sections.
f!(self.debug_abbrev)?;
f!(self.debug_str)?;
f!(self.debug_line_str)?;
f!(self.debug_line)?;
f!(self.debug_ranges)?;
f!(self.debug_rnglists)?;
f!(self.debug_loc)?;
f!(self.debug_loclists)?;
f!(self.debug_info)?;
f!(self.debug_frame)?;
f!(self.eh_frame)?;
Ok(())
}
/// For each section, call `f` once with a mutable reference.
pub fn for_each_mut<F, E>(&mut self, mut f: F) -> result::Result<(), E>
where
F: FnMut(SectionId, &mut W) -> result::Result<(), E>,
{
macro_rules! f {
($s:expr) => {
f($s.id(), &mut $s)
};
}
// Ordered so that earlier sections do not reference later sections.
f!(self.debug_abbrev)?;
f!(self.debug_str)?;
f!(self.debug_line_str)?;
f!(self.debug_line)?;
f!(self.debug_ranges)?;
f!(self.debug_rnglists)?;
f!(self.debug_loc)?;
f!(self.debug_loclists)?;
f!(self.debug_info)?;
f!(self.debug_frame)?;
f!(self.eh_frame)?;
Ok(())
}
}

172
vendor/gimli/src/write/str.rs vendored Normal file
View File

@ -0,0 +1,172 @@
use alloc::vec::Vec;
use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use crate::common::{DebugLineStrOffset, DebugStrOffset, SectionId};
use crate::write::{BaseId, Result, Section, Writer};
// Requirements:
// - values are `[u8]`, null bytes are not allowed
// - insertion returns a fixed id
// - inserting a duplicate returns the id of the existing value
// - able to convert an id to a section offset
// Optional?
// - able to get an existing value given an id
//
// Limitations of current implementation (using IndexSet):
// - inserting requires either an allocation for duplicates,
// or a double lookup for non-duplicates
// - doesn't preserve offsets when updating an existing `.debug_str` section
//
// Possible changes:
// - calculate offsets as we add values, and use that as the id.
// This would avoid the need for DebugStrOffsets but would make it
// hard to implement `get`.
macro_rules! define_string_table {
($name:ident, $id:ident, $section:ident, $offsets:ident, $docs:expr) => {
#[doc=$docs]
#[derive(Debug, Default)]
pub struct $name {
base_id: BaseId,
strings: IndexSet<Vec<u8>>,
}
impl $name {
/// Add a string to the string table and return its id.
///
/// If the string already exists, then return the id of the existing string.
///
/// # Panics
///
/// Panics if `bytes` contains a null byte.
pub fn add<T>(&mut self, bytes: T) -> $id
where
T: Into<Vec<u8>>,
{
let bytes = bytes.into();
assert!(!bytes.contains(&0));
let (index, _) = self.strings.insert_full(bytes);
$id::new(self.base_id, index)
}
/// Return the number of strings in the table.
#[inline]
pub fn count(&self) -> usize {
self.strings.len()
}
/// Get a reference to a string in the table.
///
/// # Panics
///
/// Panics if `id` is invalid.
pub fn get(&self, id: $id) -> &[u8] {
debug_assert_eq!(self.base_id, id.base_id);
self.strings.get_index(id.index).map(Vec::as_slice).unwrap()
}
/// Write the string table to the `.debug_str` section.
///
/// Returns the offsets at which the strings are written.
pub fn write<W: Writer>(&self, w: &mut $section<W>) -> Result<$offsets> {
let mut offsets = Vec::new();
for bytes in self.strings.iter() {
offsets.push(w.offset());
w.write(bytes)?;
w.write_u8(0)?;
}
Ok($offsets {
base_id: self.base_id,
offsets,
})
}
}
};
}
define_id!(StringId, "An identifier for a string in a `StringTable`.");
define_string_table!(
StringTable,
StringId,
DebugStr,
DebugStrOffsets,
"A table of strings that will be stored in a `.debug_str` section."
);
define_section!(DebugStr, DebugStrOffset, "A writable `.debug_str` section.");
define_offsets!(
DebugStrOffsets: StringId => DebugStrOffset,
"The section offsets of all strings within a `.debug_str` section."
);
define_id!(
LineStringId,
"An identifier for a string in a `LineStringTable`."
);
define_string_table!(
LineStringTable,
LineStringId,
DebugLineStr,
DebugLineStrOffsets,
"A table of strings that will be stored in a `.debug_line_str` section."
);
define_section!(
DebugLineStr,
DebugLineStrOffset,
"A writable `.debug_line_str` section."
);
define_offsets!(
DebugLineStrOffsets: LineStringId => DebugLineStrOffset,
"The section offsets of all strings within a `.debug_line_str` section."
);
#[cfg(test)]
#[cfg(feature = "read")]
mod tests {
use super::*;
use crate::read;
use crate::write::EndianVec;
use crate::LittleEndian;
#[test]
fn test_string_table() {
let mut strings = StringTable::default();
assert_eq!(strings.count(), 0);
let id1 = strings.add(&b"one"[..]);
let id2 = strings.add(&b"two"[..]);
assert_eq!(strings.add(&b"one"[..]), id1);
assert_eq!(strings.add(&b"two"[..]), id2);
assert_eq!(strings.get(id1), &b"one"[..]);
assert_eq!(strings.get(id2), &b"two"[..]);
assert_eq!(strings.count(), 2);
let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
let offsets = strings.write(&mut debug_str).unwrap();
assert_eq!(debug_str.slice(), b"one\0two\0");
assert_eq!(offsets.get(id1), DebugStrOffset(0));
assert_eq!(offsets.get(id2), DebugStrOffset(4));
assert_eq!(offsets.count(), 2);
}
#[test]
fn test_string_table_read() {
let mut strings = StringTable::default();
let id1 = strings.add(&b"one"[..]);
let id2 = strings.add(&b"two"[..]);
let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
let offsets = strings.write(&mut debug_str).unwrap();
let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
let str1 = read_debug_str.get_str(offsets.get(id1)).unwrap();
let str2 = read_debug_str.get_str(offsets.get(id2)).unwrap();
assert_eq!(str1.slice(), &b"one"[..]);
assert_eq!(str2.slice(), &b"two"[..]);
}
}

3152
vendor/gimli/src/write/unit.rs vendored Normal file

File diff suppressed because it is too large Load Diff

494
vendor/gimli/src/write/writer.rs vendored Normal file
View File

@ -0,0 +1,494 @@
use crate::common::{Format, SectionId};
use crate::constants;
use crate::endianity::Endianity;
use crate::leb128;
use crate::write::{Address, Error, Result};
/// A trait for writing the data to a DWARF section.
///
/// All write operations append to the section unless otherwise specified.
#[allow(clippy::len_without_is_empty)]
pub trait Writer {
/// The endianity of bytes that are written.
type Endian: Endianity;
/// Return the endianity of bytes that are written.
fn endian(&self) -> Self::Endian;
/// Return the current section length.
///
/// This may be used as an offset for future `write_at` calls.
fn len(&self) -> usize;
/// Write a slice.
fn write(&mut self, bytes: &[u8]) -> Result<()>;
/// Write a slice at a given offset.
///
/// The write must not extend past the current section length.
fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>;
/// Write an address.
///
/// If the writer supports relocations, then it must provide its own implementation
/// of this method.
// TODO: use write_reference instead?
fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
match address {
Address::Constant(val) => self.write_udata(val, size),
Address::Symbol { .. } => Err(Error::InvalidAddress),
}
}
/// Write an address with a `.eh_frame` pointer encoding.
///
/// The given size is only used for `DW_EH_PE_absptr` formats.
///
/// If the writer supports relocations, then it must provide its own implementation
/// of this method.
fn write_eh_pointer(
&mut self,
address: Address,
eh_pe: constants::DwEhPe,
size: u8,
) -> Result<()> {
match address {
Address::Constant(val) => {
// Indirect doesn't matter here.
let val = match eh_pe.application() {
constants::DW_EH_PE_absptr => val,
constants::DW_EH_PE_pcrel => {
// TODO: better handling of sign
let offset = self.len() as u64;
val.wrapping_sub(offset)
}
_ => {
return Err(Error::UnsupportedPointerEncoding(eh_pe));
}
};
self.write_eh_pointer_data(val, eh_pe.format(), size)
}
Address::Symbol { .. } => Err(Error::InvalidAddress),
}
}
/// Write a value with a `.eh_frame` pointer format.
///
/// The given size is only used for `DW_EH_PE_absptr` formats.
///
/// This must not be used directly for values that may require relocation.
fn write_eh_pointer_data(
&mut self,
val: u64,
format: constants::DwEhPe,
size: u8,
) -> Result<()> {
match format {
constants::DW_EH_PE_absptr => self.write_udata(val, size),
constants::DW_EH_PE_uleb128 => self.write_uleb128(val),
constants::DW_EH_PE_udata2 => self.write_udata(val, 2),
constants::DW_EH_PE_udata4 => self.write_udata(val, 4),
constants::DW_EH_PE_udata8 => self.write_udata(val, 8),
constants::DW_EH_PE_sleb128 => self.write_sleb128(val as i64),
constants::DW_EH_PE_sdata2 => self.write_sdata(val as i64, 2),
constants::DW_EH_PE_sdata4 => self.write_sdata(val as i64, 4),
constants::DW_EH_PE_sdata8 => self.write_sdata(val as i64, 8),
_ => Err(Error::UnsupportedPointerEncoding(format)),
}
}
/// Write an offset that is relative to the start of the given section.
///
/// If the writer supports relocations, then it must provide its own implementation
/// of this method.
fn write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()> {
self.write_udata(val as u64, size)
}
/// Write an offset that is relative to the start of the given section.
///
/// If the writer supports relocations, then it must provide its own implementation
/// of this method.
fn write_offset_at(
&mut self,
offset: usize,
val: usize,
_section: SectionId,
size: u8,
) -> Result<()> {
self.write_udata_at(offset, val as u64, size)
}
/// Write a reference to a symbol.
///
/// If the writer supports symbols, then it must provide its own implementation
/// of this method.
fn write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()> {
Err(Error::InvalidReference)
}
/// Write a u8.
fn write_u8(&mut self, val: u8) -> Result<()> {
let bytes = [val];
self.write(&bytes)
}
/// Write a u16.
fn write_u16(&mut self, val: u16) -> Result<()> {
let mut bytes = [0; 2];
self.endian().write_u16(&mut bytes, val);
self.write(&bytes)
}
/// Write a u32.
fn write_u32(&mut self, val: u32) -> Result<()> {
let mut bytes = [0; 4];
self.endian().write_u32(&mut bytes, val);
self.write(&bytes)
}
/// Write a u64.
fn write_u64(&mut self, val: u64) -> Result<()> {
let mut bytes = [0; 8];
self.endian().write_u64(&mut bytes, val);
self.write(&bytes)
}
/// Write a u8 at the given offset.
fn write_u8_at(&mut self, offset: usize, val: u8) -> Result<()> {
let bytes = [val];
self.write_at(offset, &bytes)
}
/// Write a u16 at the given offset.
fn write_u16_at(&mut self, offset: usize, val: u16) -> Result<()> {
let mut bytes = [0; 2];
self.endian().write_u16(&mut bytes, val);
self.write_at(offset, &bytes)
}
/// Write a u32 at the given offset.
fn write_u32_at(&mut self, offset: usize, val: u32) -> Result<()> {
let mut bytes = [0; 4];
self.endian().write_u32(&mut bytes, val);
self.write_at(offset, &bytes)
}
/// Write a u64 at the given offset.
fn write_u64_at(&mut self, offset: usize, val: u64) -> Result<()> {
let mut bytes = [0; 8];
self.endian().write_u64(&mut bytes, val);
self.write_at(offset, &bytes)
}
/// Write unsigned data of the given size.
///
/// Returns an error if the value is too large for the size.
/// This must not be used directly for values that may require relocation.
fn write_udata(&mut self, val: u64, size: u8) -> Result<()> {
match size {
1 => {
let write_val = val as u8;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u8(write_val)
}
2 => {
let write_val = val as u16;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u16(write_val)
}
4 => {
let write_val = val as u32;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u32(write_val)
}
8 => self.write_u64(val),
otherwise => Err(Error::UnsupportedWordSize(otherwise)),
}
}
/// Write signed data of the given size.
///
/// Returns an error if the value is too large for the size.
/// This must not be used directly for values that may require relocation.
fn write_sdata(&mut self, val: i64, size: u8) -> Result<()> {
match size {
1 => {
let write_val = val as i8;
if val != i64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u8(write_val as u8)
}
2 => {
let write_val = val as i16;
if val != i64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u16(write_val as u16)
}
4 => {
let write_val = val as i32;
if val != i64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u32(write_val as u32)
}
8 => self.write_u64(val as u64),
otherwise => Err(Error::UnsupportedWordSize(otherwise)),
}
}
/// Write a word of the given size at the given offset.
///
/// Returns an error if the value is too large for the size.
/// This must not be used directly for values that may require relocation.
fn write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()> {
match size {
1 => {
let write_val = val as u8;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u8_at(offset, write_val)
}
2 => {
let write_val = val as u16;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u16_at(offset, write_val)
}
4 => {
let write_val = val as u32;
if val != u64::from(write_val) {
return Err(Error::ValueTooLarge);
}
self.write_u32_at(offset, write_val)
}
8 => self.write_u64_at(offset, val),
otherwise => Err(Error::UnsupportedWordSize(otherwise)),
}
}
/// Write an unsigned LEB128 encoded integer.
fn write_uleb128(&mut self, val: u64) -> Result<()> {
let mut bytes = [0u8; 10];
// bytes is long enough so this will never fail.
let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap();
self.write(&bytes[..len])
}
/// Read an unsigned LEB128 encoded integer.
fn write_sleb128(&mut self, val: i64) -> Result<()> {
let mut bytes = [0u8; 10];
// bytes is long enough so this will never fail.
let len = leb128::write::signed(&mut { &mut bytes[..] }, val).unwrap();
self.write(&bytes[..len])
}
/// Write an initial length according to the given DWARF format.
///
/// This will only write a length of zero, since the length isn't
/// known yet, and a subsequent call to `write_initial_length_at`
/// will write the actual length.
fn write_initial_length(&mut self, format: Format) -> Result<InitialLengthOffset> {
if format == Format::Dwarf64 {
self.write_u32(0xffff_ffff)?;
}
let offset = InitialLengthOffset(self.len());
self.write_udata(0, format.word_size())?;
Ok(offset)
}
/// Write an initial length at the given offset according to the given DWARF format.
///
/// `write_initial_length` must have previously returned the offset.
fn write_initial_length_at(
&mut self,
offset: InitialLengthOffset,
length: u64,
format: Format,
) -> Result<()> {
self.write_udata_at(offset.0, length, format.word_size())
}
}
/// The offset at which an initial length should be written.
#[derive(Debug, Clone, Copy)]
pub struct InitialLengthOffset(usize);
#[cfg(test)]
mod tests {
use super::*;
use crate::write;
use crate::{BigEndian, LittleEndian};
use std::{i64, u64};
#[test]
fn test_writer() {
let mut w = write::EndianVec::new(LittleEndian);
w.write_address(Address::Constant(0x1122_3344), 4).unwrap();
assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
assert_eq!(
w.write_address(
Address::Symbol {
symbol: 0,
addend: 0
},
4
),
Err(Error::InvalidAddress)
);
let mut w = write::EndianVec::new(LittleEndian);
w.write_offset(0x1122_3344, SectionId::DebugInfo, 4)
.unwrap();
assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
w.write_offset_at(1, 0x5566, SectionId::DebugInfo, 2)
.unwrap();
assert_eq!(w.slice(), &[0x44, 0x66, 0x55, 0x11]);
let mut w = write::EndianVec::new(LittleEndian);
w.write_u8(0x11).unwrap();
w.write_u16(0x2233).unwrap();
w.write_u32(0x4455_6677).unwrap();
w.write_u64(0x8081_8283_8485_8687).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x11,
0x33, 0x22,
0x77, 0x66, 0x55, 0x44,
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
]);
w.write_u8_at(14, 0x11).unwrap();
w.write_u16_at(12, 0x2233).unwrap();
w.write_u32_at(8, 0x4455_6677).unwrap();
w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
0x77, 0x66, 0x55, 0x44,
0x33, 0x22,
0x11,
]);
let mut w = write::EndianVec::new(BigEndian);
w.write_u8(0x11).unwrap();
w.write_u16(0x2233).unwrap();
w.write_u32(0x4455_6677).unwrap();
w.write_u64(0x8081_8283_8485_8687).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x11,
0x22, 0x33,
0x44, 0x55, 0x66, 0x77,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
]);
w.write_u8_at(14, 0x11).unwrap();
w.write_u16_at(12, 0x2233).unwrap();
w.write_u32_at(8, 0x4455_6677).unwrap();
w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x44, 0x55, 0x66, 0x77,
0x22, 0x33,
0x11,
]);
let mut w = write::EndianVec::new(LittleEndian);
w.write_udata(0x11, 1).unwrap();
w.write_udata(0x2233, 2).unwrap();
w.write_udata(0x4455_6677, 4).unwrap();
w.write_udata(0x8081_8283_8485_8687, 8).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x11,
0x33, 0x22,
0x77, 0x66, 0x55, 0x44,
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
]);
assert_eq!(w.write_udata(0x100, 1), Err(Error::ValueTooLarge));
assert_eq!(w.write_udata(0x1_0000, 2), Err(Error::ValueTooLarge));
assert_eq!(w.write_udata(0x1_0000_0000, 4), Err(Error::ValueTooLarge));
assert_eq!(w.write_udata(0x00, 3), Err(Error::UnsupportedWordSize(3)));
w.write_udata_at(14, 0x11, 1).unwrap();
w.write_udata_at(12, 0x2233, 2).unwrap();
w.write_udata_at(8, 0x4455_6677, 4).unwrap();
w.write_udata_at(0, 0x8081_8283_8485_8687, 8).unwrap();
#[rustfmt::skip]
assert_eq!(w.slice(), &[
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
0x77, 0x66, 0x55, 0x44,
0x33, 0x22,
0x11,
]);
assert_eq!(w.write_udata_at(0, 0x100, 1), Err(Error::ValueTooLarge));
assert_eq!(w.write_udata_at(0, 0x1_0000, 2), Err(Error::ValueTooLarge));
assert_eq!(
w.write_udata_at(0, 0x1_0000_0000, 4),
Err(Error::ValueTooLarge)
);
assert_eq!(
w.write_udata_at(0, 0x00, 3),
Err(Error::UnsupportedWordSize(3))
);
let mut w = write::EndianVec::new(LittleEndian);
w.write_uleb128(0).unwrap();
assert_eq!(w.slice(), &[0]);
let mut w = write::EndianVec::new(LittleEndian);
w.write_uleb128(u64::MAX).unwrap();
assert_eq!(
w.slice(),
&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1]
);
let mut w = write::EndianVec::new(LittleEndian);
w.write_sleb128(0).unwrap();
assert_eq!(w.slice(), &[0]);
let mut w = write::EndianVec::new(LittleEndian);
w.write_sleb128(i64::MAX).unwrap();
assert_eq!(
w.slice(),
&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0]
);
let mut w = write::EndianVec::new(LittleEndian);
w.write_sleb128(i64::MIN).unwrap();
assert_eq!(
w.slice(),
&[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f]
);
let mut w = write::EndianVec::new(LittleEndian);
let offset = w.write_initial_length(Format::Dwarf32).unwrap();
assert_eq!(w.slice(), &[0, 0, 0, 0]);
w.write_initial_length_at(offset, 0x1122_3344, Format::Dwarf32)
.unwrap();
assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
assert_eq!(
w.write_initial_length_at(offset, 0x1_0000_0000, Format::Dwarf32),
Err(Error::ValueTooLarge)
);
let mut w = write::EndianVec::new(LittleEndian);
let offset = w.write_initial_length(Format::Dwarf64).unwrap();
assert_eq!(w.slice(), &[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0]);
w.write_initial_length_at(offset, 0x1122_3344_5566_7788, Format::Dwarf64)
.unwrap();
assert_eq!(
w.slice(),
&[0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]
);
}
}