From a990de90fe41456a23e58bd087d2f107d321f3a1 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Fri, 19 Jul 2024 16:37:58 +0400 Subject: Deleted vendor folder --- vendor/object/.cargo-checksum.json | 1 - vendor/object/CHANGELOG.md | 754 --- vendor/object/Cargo.toml | 163 - vendor/object/LICENSE-APACHE | 201 - vendor/object/LICENSE-MIT | 25 - vendor/object/README.md | 56 - vendor/object/clippy.toml | 1 - vendor/object/src/archive.rs | 91 - vendor/object/src/common.rs | 536 -- vendor/object/src/elf.rs | 6287 ----------------------- vendor/object/src/endian.rs | 831 --- vendor/object/src/lib.rs | 99 - vendor/object/src/macho.rs | 3307 ------------ vendor/object/src/pe.rs | 3056 ----------- vendor/object/src/pod.rs | 239 - vendor/object/src/read/any.rs | 1328 ----- vendor/object/src/read/archive.rs | 759 --- vendor/object/src/read/coff/comdat.rs | 211 - vendor/object/src/read/coff/file.rs | 381 -- vendor/object/src/read/coff/import.rs | 220 - vendor/object/src/read/coff/mod.rs | 66 - vendor/object/src/read/coff/relocation.rs | 106 - vendor/object/src/read/coff/section.rs | 585 --- vendor/object/src/read/coff/symbol.rs | 635 --- vendor/object/src/read/elf/attributes.rs | 307 -- vendor/object/src/read/elf/comdat.rs | 162 - vendor/object/src/read/elf/compression.rs | 56 - vendor/object/src/read/elf/dynamic.rs | 117 - vendor/object/src/read/elf/file.rs | 916 ---- vendor/object/src/read/elf/hash.rs | 224 - vendor/object/src/read/elf/mod.rs | 78 - vendor/object/src/read/elf/note.rs | 271 - vendor/object/src/read/elf/relocation.rs | 628 --- vendor/object/src/read/elf/section.rs | 1150 ----- vendor/object/src/read/elf/segment.rs | 334 -- vendor/object/src/read/elf/symbol.rs | 595 --- vendor/object/src/read/elf/version.rs | 424 -- vendor/object/src/read/macho/dyld_cache.rs | 344 -- vendor/object/src/read/macho/fat.rs | 122 - vendor/object/src/read/macho/file.rs | 781 --- vendor/object/src/read/macho/load_command.rs | 382 -- vendor/object/src/read/macho/mod.rs | 72 - vendor/object/src/read/macho/relocation.rs | 158 - vendor/object/src/read/macho/section.rs | 389 -- vendor/object/src/read/macho/segment.rs | 303 -- vendor/object/src/read/macho/symbol.rs | 492 -- vendor/object/src/read/mod.rs | 860 ---- vendor/object/src/read/pe/data_directory.rs | 213 - vendor/object/src/read/pe/export.rs | 333 -- vendor/object/src/read/pe/file.rs | 1050 ---- vendor/object/src/read/pe/import.rs | 337 -- vendor/object/src/read/pe/mod.rs | 68 - vendor/object/src/read/pe/relocation.rs | 92 - vendor/object/src/read/pe/resource.rs | 209 - vendor/object/src/read/pe/rich.rs | 91 - vendor/object/src/read/pe/section.rs | 440 -- vendor/object/src/read/read_cache.rs | 178 - vendor/object/src/read/read_ref.rs | 137 - vendor/object/src/read/traits.rs | 551 -- vendor/object/src/read/util.rs | 425 -- vendor/object/src/read/wasm.rs | 966 ---- vendor/object/src/read/xcoff/comdat.rs | 135 - vendor/object/src/read/xcoff/file.rs | 696 --- vendor/object/src/read/xcoff/mod.rs | 63 - vendor/object/src/read/xcoff/relocation.rs | 127 - vendor/object/src/read/xcoff/section.rs | 431 -- vendor/object/src/read/xcoff/segment.rs | 117 - vendor/object/src/read/xcoff/symbol.rs | 786 --- vendor/object/src/write/coff/mod.rs | 10 - vendor/object/src/write/coff/object.rs | 583 --- vendor/object/src/write/coff/writer.rs | 518 -- vendor/object/src/write/elf/mod.rs | 9 - vendor/object/src/write/elf/object.rs | 907 ---- vendor/object/src/write/elf/writer.rs | 2143 -------- vendor/object/src/write/macho.rs | 1095 ---- vendor/object/src/write/mod.rs | 961 ---- vendor/object/src/write/pe.rs | 847 --- vendor/object/src/write/string.rs | 159 - vendor/object/src/write/util.rs | 260 - vendor/object/src/write/xcoff.rs | 556 -- vendor/object/src/xcoff.rs | 905 ---- vendor/object/tests/integration.rs | 2 - vendor/object/tests/parse_self.rs | 25 - vendor/object/tests/read/coff.rs | 23 - vendor/object/tests/read/mod.rs | 3 - vendor/object/tests/round_trip/bss.rs | 255 - vendor/object/tests/round_trip/coff.rs | 56 - vendor/object/tests/round_trip/comdat.rs | 225 - vendor/object/tests/round_trip/common.rs | 245 - vendor/object/tests/round_trip/elf.rs | 289 -- vendor/object/tests/round_trip/macho.rs | 64 - vendor/object/tests/round_trip/mod.rs | 686 --- vendor/object/tests/round_trip/section_flags.rs | 90 - vendor/object/tests/round_trip/tls.rs | 316 -- 94 files changed, 47780 deletions(-) delete mode 100644 vendor/object/.cargo-checksum.json delete mode 100644 vendor/object/CHANGELOG.md delete mode 100644 vendor/object/Cargo.toml delete mode 100644 vendor/object/LICENSE-APACHE delete mode 100644 vendor/object/LICENSE-MIT delete mode 100644 vendor/object/README.md delete mode 100644 vendor/object/clippy.toml delete mode 100644 vendor/object/src/archive.rs delete mode 100644 vendor/object/src/common.rs delete mode 100644 vendor/object/src/elf.rs delete mode 100644 vendor/object/src/endian.rs delete mode 100644 vendor/object/src/lib.rs delete mode 100644 vendor/object/src/macho.rs delete mode 100644 vendor/object/src/pe.rs delete mode 100644 vendor/object/src/pod.rs delete mode 100644 vendor/object/src/read/any.rs delete mode 100644 vendor/object/src/read/archive.rs delete mode 100644 vendor/object/src/read/coff/comdat.rs delete mode 100644 vendor/object/src/read/coff/file.rs delete mode 100644 vendor/object/src/read/coff/import.rs delete mode 100644 vendor/object/src/read/coff/mod.rs delete mode 100644 vendor/object/src/read/coff/relocation.rs delete mode 100644 vendor/object/src/read/coff/section.rs delete mode 100644 vendor/object/src/read/coff/symbol.rs delete mode 100644 vendor/object/src/read/elf/attributes.rs delete mode 100644 vendor/object/src/read/elf/comdat.rs delete mode 100644 vendor/object/src/read/elf/compression.rs delete mode 100644 vendor/object/src/read/elf/dynamic.rs delete mode 100644 vendor/object/src/read/elf/file.rs delete mode 100644 vendor/object/src/read/elf/hash.rs delete mode 100644 vendor/object/src/read/elf/mod.rs delete mode 100644 vendor/object/src/read/elf/note.rs delete mode 100644 vendor/object/src/read/elf/relocation.rs delete mode 100644 vendor/object/src/read/elf/section.rs delete mode 100644 vendor/object/src/read/elf/segment.rs delete mode 100644 vendor/object/src/read/elf/symbol.rs delete mode 100644 vendor/object/src/read/elf/version.rs delete mode 100644 vendor/object/src/read/macho/dyld_cache.rs delete mode 100644 vendor/object/src/read/macho/fat.rs delete mode 100644 vendor/object/src/read/macho/file.rs delete mode 100644 vendor/object/src/read/macho/load_command.rs delete mode 100644 vendor/object/src/read/macho/mod.rs delete mode 100644 vendor/object/src/read/macho/relocation.rs delete mode 100644 vendor/object/src/read/macho/section.rs delete mode 100644 vendor/object/src/read/macho/segment.rs delete mode 100644 vendor/object/src/read/macho/symbol.rs delete mode 100644 vendor/object/src/read/mod.rs delete mode 100644 vendor/object/src/read/pe/data_directory.rs delete mode 100644 vendor/object/src/read/pe/export.rs delete mode 100644 vendor/object/src/read/pe/file.rs delete mode 100644 vendor/object/src/read/pe/import.rs delete mode 100644 vendor/object/src/read/pe/mod.rs delete mode 100644 vendor/object/src/read/pe/relocation.rs delete mode 100644 vendor/object/src/read/pe/resource.rs delete mode 100644 vendor/object/src/read/pe/rich.rs delete mode 100644 vendor/object/src/read/pe/section.rs delete mode 100644 vendor/object/src/read/read_cache.rs delete mode 100644 vendor/object/src/read/read_ref.rs delete mode 100644 vendor/object/src/read/traits.rs delete mode 100644 vendor/object/src/read/util.rs delete mode 100644 vendor/object/src/read/wasm.rs delete mode 100644 vendor/object/src/read/xcoff/comdat.rs delete mode 100644 vendor/object/src/read/xcoff/file.rs delete mode 100644 vendor/object/src/read/xcoff/mod.rs delete mode 100644 vendor/object/src/read/xcoff/relocation.rs delete mode 100644 vendor/object/src/read/xcoff/section.rs delete mode 100644 vendor/object/src/read/xcoff/segment.rs delete mode 100644 vendor/object/src/read/xcoff/symbol.rs delete mode 100644 vendor/object/src/write/coff/mod.rs delete mode 100644 vendor/object/src/write/coff/object.rs delete mode 100644 vendor/object/src/write/coff/writer.rs delete mode 100644 vendor/object/src/write/elf/mod.rs delete mode 100644 vendor/object/src/write/elf/object.rs delete mode 100644 vendor/object/src/write/elf/writer.rs delete mode 100644 vendor/object/src/write/macho.rs delete mode 100644 vendor/object/src/write/mod.rs delete mode 100644 vendor/object/src/write/pe.rs delete mode 100644 vendor/object/src/write/string.rs delete mode 100644 vendor/object/src/write/util.rs delete mode 100644 vendor/object/src/write/xcoff.rs delete mode 100644 vendor/object/src/xcoff.rs delete mode 100644 vendor/object/tests/integration.rs delete mode 100644 vendor/object/tests/parse_self.rs delete mode 100644 vendor/object/tests/read/coff.rs delete mode 100644 vendor/object/tests/read/mod.rs delete mode 100644 vendor/object/tests/round_trip/bss.rs delete mode 100644 vendor/object/tests/round_trip/coff.rs delete mode 100644 vendor/object/tests/round_trip/comdat.rs delete mode 100644 vendor/object/tests/round_trip/common.rs delete mode 100644 vendor/object/tests/round_trip/elf.rs delete mode 100644 vendor/object/tests/round_trip/macho.rs delete mode 100644 vendor/object/tests/round_trip/mod.rs delete mode 100644 vendor/object/tests/round_trip/section_flags.rs delete mode 100644 vendor/object/tests/round_trip/tls.rs (limited to 'vendor/object') diff --git a/vendor/object/.cargo-checksum.json b/vendor/object/.cargo-checksum.json deleted file mode 100644 index ae4a4fb..0000000 --- a/vendor/object/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"8b7856a7b2ed9d534abaf22e924f28b7dc470ee62b8b83a81836111e8e6b8a17","Cargo.toml":"7a6f454c405b4debc0ba393deac7d32bb844745f80d1e42bc6aa6ca30f2078cd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"f2e83094c790fee1543503a19763c80afbfc35ab3bcf9e273e0efef0646ca181","clippy.toml":"e1e95839ba8e8bbf07f99ff49e2f151b9048c7981301a5480571842bbaf78ca2","src/archive.rs":"d6cead723242c26db2967b63385b79ed2008980a8c64b123a5eecffd7ed388fc","src/common.rs":"4b08104045d9f4fc6b0cd87d273a694e3a442d38e8cea88dadaf56202069310b","src/elf.rs":"76013b28af828ea4828c2fdce1ccc0753330bbb59f92b0feeb2902ca5277a931","src/endian.rs":"b4f63a85ccd3d5c11615baf5ba946c82046c221a1b8c74ee8c6fa4360782980c","src/lib.rs":"e9344c09eaaa38b3b68c5721da7593c35b21bcd19e2f8fa8b9e086359883fef1","src/macho.rs":"e62808b0c84494b68e7e69b2f7fd9c0620b2ef61b6a2af3403de30284cf6b898","src/pe.rs":"cd61391b064bea4c99cff515d9c635227218cf62b7aa719b66e3b1935379c497","src/pod.rs":"d2967732f0052e6cfa18a2dd62c57bc3b640a20eb9a6db9f39836000ceabb399","src/read/any.rs":"8b9c1c4d3e42a4a31d8aa3a8e00873eeb59c39e39a95f18375414046386c55a3","src/read/archive.rs":"e72051dc3315ca5c8e43eae0ab68dadef774f2e88f7755cd663ee0996b567d9a","src/read/coff/comdat.rs":"bc48209a993c67d9151d45e6cb0c4d05781cba50fc3ee19261adca6ef49772de","src/read/coff/file.rs":"bac38db07bee4d05342da7df2d352fd6d9bb41d684531f643916f4c4612b14dc","src/read/coff/import.rs":"2688a34ae2169e93405a4aad2380e15a28edd2db94286becd6644e9996ceb7b2","src/read/coff/mod.rs":"c3b0c4f09993b07a85fda3dd2de9c80258aaadce6c0598eb25e55fab4c6bbf1c","src/read/coff/relocation.rs":"001c5dab38a3f49d3a07ea9be78e1c6fe085a34accc041916b82779dd003177e","src/read/coff/section.rs":"cf4d098074ef45e25e98466cc2edb17f4209c955508c550fd8281a93fd5d10db","src/read/coff/symbol.rs":"b4323e6d905c520e43c1886f71423048397fdcda685e66be673f5dcaa62ee48f","src/read/elf/attributes.rs":"a9ac569d6ce02c98af70f83dcc74b0e27d008da5471851d6d307ecb270f60468","src/read/elf/comdat.rs":"44f281b8b2f7f763ac79bc8136e7f06bb9c145ff445054789fb0e045987b8904","src/read/elf/compression.rs":"726bb1ca96a480ac2a0c8ccaa4c2291d62ca6c4af2b1a2e43b74ae7be17f6d75","src/read/elf/dynamic.rs":"c934f8b72d71ed39ff129ce37a8177b5bf12fba93695914eae48112bf89702b4","src/read/elf/file.rs":"cc088179cae5c961991a553df10a52f61a5ee4122f9683faf988f94f5f209c3f","src/read/elf/hash.rs":"caf8cd5eb547bd212c3ecff5d33b39bc22f68e1d78de72a9333c0062e06e0507","src/read/elf/mod.rs":"7c0d4d10c1055f57184f470aa014e6358394ec95019a74da8d5079d275437d0b","src/read/elf/note.rs":"ca7fe4d04fe130e7c29bea5f5f559f4561272e4658a502444164003f36e620ec","src/read/elf/relocation.rs":"e43491ecfcd84b3a4b01d595cb28aea85fde5f8968a21053c0f28ae2fc4c5bc6","src/read/elf/section.rs":"c0ea5bc99c22791e2992dc348769bc72cfffac637ac6881cd34b3e1a767a692b","src/read/elf/segment.rs":"a9b235d4193e879957c0c929830870cbe57cb0305f5d9ed10911c4fe10b19430","src/read/elf/symbol.rs":"ed4f3cdffe33435a600561d8cc0c20842c58c8c922cfdac9067eaab6d1e37cf7","src/read/elf/version.rs":"70d2d9a0eae9d4602a79bbf8cc03e689921801b7d463a4381b331df534e59fda","src/read/macho/dyld_cache.rs":"855845db4eeaae89513e525786adc9f42225e3a4ec0e3a063629e87dd29f1059","src/read/macho/fat.rs":"a57272f0cd4bfdbacad1aac953e874631fcc445ce406b990892630542cdf2bda","src/read/macho/file.rs":"2d33692bae78ac7f07f946044c5c54c1294e774f7dc530181b9683e440828ba7","src/read/macho/load_command.rs":"bcb912923b5da843670275451ccb94527d50fa97d643b28924377f1c83d2339b","src/read/macho/mod.rs":"0e97e28f379766511f33d8ccb97eaa690a352f9180080a376a86516249b1bdd8","src/read/macho/relocation.rs":"be5d2588d7e6ccb0b9dda6f495eb0bc730eb01eb129e0a418ce5dce2ebb7de69","src/read/macho/section.rs":"dfc40939fc511bb6ad784eef7465d8c224d8efc246fceacaa7c8e4c6153e1f48","src/read/macho/segment.rs":"4888f4020ff98e7495405865631a3de4f1d1f21cc9df157900d689b0f64791f0","src/read/macho/symbol.rs":"f51e723355d84270d05bf289cefa4bcc35815f00ad075c2d63289e2d6ee6e9fd","src/read/mod.rs":"c53ea9bbf3129c4a837db5aebe3f4ae6ed05eb71f3305499a1434c8548a35f31","src/read/pe/data_directory.rs":"730c5b90174ddcce49f78fc9ff6fbdde0a011dc7d50154c8fe3a5a8b1a09a015","src/read/pe/export.rs":"88cd068d1ed84c1153f94ee5d71d9d9dc07de4a65499938379006e2d0801f592","src/read/pe/file.rs":"d88319d9e1358f5c0f1789c85770d144b45b94c6273e901682645acc717e2113","src/read/pe/import.rs":"5d5cedc95294cbfbab705b48e87bce29b57b083c17e47ce09806cf53588d2859","src/read/pe/mod.rs":"f0c70bf86680e7afdfdffbf4f3118efc9801516c6898663f574b115b62b1fbcd","src/read/pe/relocation.rs":"27795df870bc38b3aab57a9ef78c141633442727dbcd5b1c4b61513ec64069a6","src/read/pe/resource.rs":"1cbac8460d717c6fb5782aaad25a9c4148a1fbf050bd33b0eef476116b072711","src/read/pe/rich.rs":"ae9b2fc927bab2661e8d200a10128aebde37d26b50cb9069e9af9eb7bacee591","src/read/pe/section.rs":"5658ab6c7fc3b03c646d8dc28e795b5ec7a047ba7065db037d82b6f71ecbd81f","src/read/read_cache.rs":"775c3b357898981b5944302f2d773d637ac0dc6e26074023863153d30101b657","src/read/read_ref.rs":"712d276e6891f4cf512ed35be73ce2872ecd25c523c8554bdfd175445e120e56","src/read/traits.rs":"53a234182e58450b80972350b5645916877e6c30b4bd9ee8ed569deff7bef28a","src/read/util.rs":"03f3dc16d43e0b351feaff4e47f5cb996f9cc05e540e7996bff6961ff9901034","src/read/wasm.rs":"34c5a7344efcc57105f105282deb22b4dd3641394f518fb25aa9d7ea7ab2319f","src/read/xcoff/comdat.rs":"d054619dabe880f90b9a7935d13e8aaf35b10c7a52bd6d517cb93f1fc9a847d1","src/read/xcoff/file.rs":"dfa599bab234220089cf8b891dae299d1a760366535956ad55fe70b5e179b167","src/read/xcoff/mod.rs":"40921a3e9d65360f57c7301f11dd12ec82f71311b689272f209758ecbc755eb3","src/read/xcoff/relocation.rs":"b383d883f8966a4d9da8de5c2146b324e8758500ea73fd1c51c0216407db6ce9","src/read/xcoff/section.rs":"b39d79d680ce48de13526ca3dfbbb39baece92174e6732fa040418e1d4cfe89c","src/read/xcoff/segment.rs":"ce6f0c1c6dd5aa3dce620c7645fa9c790ee56765b6586782ac0e747c0e949f79","src/read/xcoff/symbol.rs":"c15031c2a0fd8cc7202087adac14baf8abbdd5ffb30d0f4b6bbbea9024e1ada0","src/write/coff/mod.rs":"511bd3a19575b1d888d0d1abb17bb697c36eda0e7032375afb13daedc972c27e","src/write/coff/object.rs":"13c8e7ca89a470280cae8478fe2637a518d81a087af2958868611c4e6a39f4cf","src/write/coff/writer.rs":"65754d28af57fc5a415af5665759a728e4526d13052f50dc7f2c00f3e307b225","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"ebb433b0e5afa4945b6ac2152137f56331507a2b5d8e8e698052f77ccb351486","src/write/elf/writer.rs":"84336230a24413a41e342735c153c3421c70707ec92c2df02e7d3536e5d41b55","src/write/macho.rs":"28d41a8423f4652d558c43fd9abf86488e60dc0be311aa4ddc4a863879179707","src/write/mod.rs":"7561a31d1e5da73a8c56b742ed550deffa1dd64ddf33e46d12ffde464906df61","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"0033a6f5137b42988ac41dbaa2efb94a4d74d8b043c9a34c40125e8ee6912420","src/write/util.rs":"d93a7d00260cf6df0cca481d5fb5845ee5a87787dc4fc35a64f2abeb91096965","src/write/xcoff.rs":"290e98f8c71baafc1f2111e1513f35a95a7f7914cc0f446bbc24547a17eb3af1","src/xcoff.rs":"bfcfbcea61436aa41a6fc8ee2395654552d1dadd3d0e17d7e11679c65b7978aa","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"d3ec2079f00237640d01cb66eb24c55c85d7a775bb94f9f5c9f77e21cb7a785d","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"d7351d888ccad246a646ab3bea1afc3d445adeb28c5d3c8f157f7cde3717281c","tests/round_trip/macho.rs":"f6566e658f8c627668646763010a3872fd7b7b0a5aebeed00b0690acad90d147","tests/round_trip/mod.rs":"a7ac4075f61ddec0b6bf87e7d447ba27bab01c8ae0b14d78af87bcc9df34fe9c","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"302f46d7481e1738b7561057869cec33d03b8760aba1d78ef0fe5adf603001f6"},"package":"a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"} \ No newline at end of file diff --git a/vendor/object/CHANGELOG.md b/vendor/object/CHANGELOG.md deleted file mode 100644 index 12c8653..0000000 --- a/vendor/object/CHANGELOG.md +++ /dev/null @@ -1,754 +0,0 @@ -# `object` Change Log - --------------------------------------------------------------------------------- - -## 0.32.2 - -Released 2023/12/24. - -### Added - -* Added ELF relocations for LoongArch ABI v2.20. - [#578](https://github.com/gimli-rs/object/pull/578) - [#589](https://github.com/gimli-rs/object/pull/589) - -* Added ELF support for SHARC. - [#593](https://github.com/gimli-rs/object/pull/593) - -* Added `write::coff::Writer`. - [#595](https://github.com/gimli-rs/object/pull/595) - -* Added `SubArchitecture::Arm64EC` support for PE/COFF. - [#607](https://github.com/gimli-rs/object/pull/607) - -* Added `SubArchitecture::Arm64E` support for Mach-O. - [#614](https://github.com/gimli-rs/object/pull/614) - -* Added `read::Object::symbol_by_name` and `read::Object::symbol_by_name_bytes`. - [#602](https://github.com/gimli-rs/object/pull/602) - -* Added more functions to the low level API in `read::xcoff`. - [#608](https://github.com/gimli-rs/object/pull/608) - -* Added more functions to the low level API in `read::macho`. - [#584](https://github.com/gimli-rs/object/pull/584) - -### Changed - -* Fixes for AArch64 relocation addends for Mach-O. - [#581](https://github.com/gimli-rs/object/pull/581) - -* Changes to `write::Object` output for Mach-O, including the addition of a `LC_DYSYMTAB` load command. - [#584](https://github.com/gimli-rs/object/pull/584) - -* Changed `write::Object` to always use `R_X86_64_PLT32` for x86-64 branches for ELF. - [#590](https://github.com/gimli-rs/object/pull/590) - -* Fixed `read::ObjectSymbol::kind` for undefined section symbols for COFF. - [#592](https://github.com/gimli-rs/object/pull/592) - -* Fixed `write::Object` to accept undefined section symbols for COFF. - [#594](https://github.com/gimli-rs/object/pull/594) - -* Improved parsing of auxiliary section symbols for COFF. - [#603](https://github.com/gimli-rs/object/pull/603) - -* Improved the selection of symbols for `read::Object::symbol_map`. - This includes changes to `read::Symbol::is_definition`. - [#601](https://github.com/gimli-rs/object/pull/601) - [#606](https://github.com/gimli-rs/object/pull/606) - -* Changed `read::ObjectSymbol::kind` for ELF `STT_NOTYPE` symbols to `SymbolKind::Unknown`. - [#604](https://github.com/gimli-rs/object/pull/604) - -* Changed `read::ObjectSymbol::scope` for XCOFF `C_HIDEXT` symbols to `SymbolScope::Compilation`. - [#605](https://github.com/gimli-rs/object/pull/605) - --------------------------------------------------------------------------------- - -## 0.32.1 - -Released 2023/09/03. - -### Added - -* Added `write::Object::set_macho_cpu_subtype`. - [#574](https://github.com/gimli-rs/object/pull/574) - --------------------------------------------------------------------------------- - -## 0.32.0 - -Released 2023/08/12. - -### Breaking changes - -* Changed `read::elf::Note::name` to exclude all trailing null bytes. - [#549](https://github.com/gimli-rs/object/pull/549) - -* Updated dependencies, and changed some optional dependencies to use the `dep:` - feature syntax. - [#558](https://github.com/gimli-rs/object/pull/558) - [#569](https://github.com/gimli-rs/object/pull/569) - -### Changed - -* The minimum supported rust version for the `read` feature and its dependencies - has changed to 1.60.0. - -* The minimum supported rust version for other features has changed to 1.65.0. - -* Changed many definitions from `static` to `const`. - [#549](https://github.com/gimli-rs/object/pull/549) - -* Fixed Mach-O section alignment padding in `write::Object`. - [#553](https://github.com/gimli-rs/object/pull/553) - -* Changed `read::File` to an enum. - [#564](https://github.com/gimli-rs/object/pull/564) - -### Added - -* Added `elf::ELF_NOTE_GO`, `elf::NT_GO_BUILD_ID`, and `read::elf::Note::name_bytes`. - [#549](https://github.com/gimli-rs/object/pull/549) - -* Added `read::FileKind::CoffImport` and `read::coff::ImportFile`. - [#555](https://github.com/gimli-rs/object/pull/555) - [#556](https://github.com/gimli-rs/object/pull/556) - -* Added `Architecture::Csky` and basic ELF support for C-SKY. - [#561](https://github.com/gimli-rs/object/pull/561) - -* Added `read::elf::ElfSymbol::raw_symbol`. - [#562](https://github.com/gimli-rs/object/pull/562) - --------------------------------------------------------------------------------- - -## 0.30.4 - -Released 2023/06/05. - -### Changed - -* Fixed Mach-O section alignment padding in `write::Object`. - [#553](https://github.com/gimli-rs/object/pull/553) - --------------------------------------------------------------------------------- - -## 0.31.1 - -Released 2023/05/09. - -### Changed - -* Fixed address for global symbols in `read::wasm`. - [#539](https://github.com/gimli-rs/object/pull/539) - -* Fixed writing of alignment for empty ELF sections. - [#540](https://github.com/gimli-rs/object/pull/540) - -### Added - -* Added more `elf::GNU_PROPERTY_*` definitions. - Added `read::elf::note::gnu_properties`, `write::StandardSection::GnuProperty`, - and `write::Object::add_elf_gnu_property_u32`. - [#537](https://github.com/gimli-rs/object/pull/537) - [#541](https://github.com/gimli-rs/object/pull/541) - -* Added Mach-O support for `Architecture::Aarch64_Ilp32`. - [#542](https://github.com/gimli-rs/object/pull/542) - [#545](https://github.com/gimli-rs/object/pull/545) - -* Added `Architecture::Wasm64`. - [#543](https://github.com/gimli-rs/object/pull/543) - --------------------------------------------------------------------------------- - -## 0.31.0 - -Released 2023/04/14. - -### Breaking changes - -* Added a type parameter on existing COFF types to support reading COFF `/bigobj` files. - [#502](https://github.com/gimli-rs/object/pull/502) - -* Changed PE symbols to support COFF `/bigobj`. - Changed `pe::IMAGE_SYM_*` to `i32`. - Changed `pe::ImageSymbolEx::section_number` to `I32Bytes`. - Deleted a number of methods from `pe::ImageSymbol`. - Use the `read::pe::ImageSymbol` trait instead. - [#502](https://github.com/gimli-rs/object/pull/502) - -* Changed `pe::Guid` to a single array, and added methods to read the individual fields. - [#502](https://github.com/gimli-rs/object/pull/502) - -* Added `Symbol` type parameter to `SymbolFlags` to support `SymbolFlags::Xcoff`. - [#527](https://github.com/gimli-rs/object/pull/527) - -### Changed - -* Fix alignment when reserving zero length sections in `write::elf::Write::reserve`. - [#514](https://github.com/gimli-rs/object/pull/514) - -* Validate command size in `read::macho::LoadCommandIterator`. - [#516](https://github.com/gimli-rs/object/pull/516) - -* Handle invalid alignment in `read::macho::MachoSection::align`. - [#516](https://github.com/gimli-rs/object/pull/516) - -* Accept `SymbolKind::Unknown` in `write::Object::macho_write`. - [#519](https://github.com/gimli-rs/object/pull/519) - -* Updated `wasmparser` dependency. - [#528](https://github.com/gimli-rs/object/pull/528) - -### Added - -* Added more `elf::EF_RISCV_*` definitions. - [#507](https://github.com/gimli-rs/object/pull/507) - -* Added `read::elf::SectionHeader::gnu_attributes` and associated types. - Added `.gnu.attributes` support to `write::elf::Writer`. - [#509](https://github.com/gimli-rs/object/pull/509) - [#525](https://github.com/gimli-rs/object/pull/525) - -* Added `write::Object::set_macho_build_version`. - [#524](https://github.com/gimli-rs/object/pull/524) - -* Added `read::FileKind::Xcoff32`, `read::FileKind::Xcoff64`, `read::XcoffFile`, - and associated types. - Added XCOFF support to `write::Object`. - [#469](https://github.com/gimli-rs/object/pull/469) - [#476](https://github.com/gimli-rs/object/pull/476) - [#477](https://github.com/gimli-rs/object/pull/477) - [#482](https://github.com/gimli-rs/object/pull/482) - [#484](https://github.com/gimli-rs/object/pull/484) - [#486](https://github.com/gimli-rs/object/pull/486) - [#527](https://github.com/gimli-rs/object/pull/527) - -* Added `read::FileKind::CoffBig`, `read::pe::CoffHeader` and `read::pe::ImageSymbol`. - [#502](https://github.com/gimli-rs/object/pull/502) - -* Added `elf::PT_GNU_PROPERTY`. - [#530](https://github.com/gimli-rs/object/pull/530) - -* Added `elf::ELFCOMPRESS_ZSTD`, `read::CompressionFormat::Zstandard`, - and Zstandard decompression in `read::CompressedData::decompress` using - the `ruzstd` crate. - [#532](https://github.com/gimli-rs/object/pull/532) - -* Added `read::elf::NoteIterator::new`. - [#533](https://github.com/gimli-rs/object/pull/533) - --------------------------------------------------------------------------------- - -## 0.30.3 - -Released 2023/01/23. - -### Added - -* Added `SectionKind::ReadOnlyDataWithRel` for writing. - [#504](https://github.com/gimli-rs/object/pull/504) - --------------------------------------------------------------------------------- - -## 0.30.2 - -Released 2023/01/11. - -### Added - -* Added more ELF constants for AVR flags and relocations. - [#500](https://github.com/gimli-rs/object/pull/500) - --------------------------------------------------------------------------------- - -## 0.30.1 - -Released 2023/01/04. - -### Changed - -* Changed `read::ElfSymbol::kind` to handle `STT_NOTYPE` and `STT_GNU_IFUNC`. - [#498](https://github.com/gimli-rs/object/pull/498) - -### Added - -* Added `read::CoffSymbol::raw_symbol`. - [#494](https://github.com/gimli-rs/object/pull/494) - -* Added ELF support for Solana Binary Format. - [#491](https://github.com/gimli-rs/object/pull/491) - -* Added ELF support for AArch64 ILP32. - [#497](https://github.com/gimli-rs/object/pull/497) - --------------------------------------------------------------------------------- - -## 0.30.0 - -Released 2022/11/22. - -### Breaking changes - -* The minimum supported rust version for the `read` feature has changed to 1.52.0. - [#458](https://github.com/gimli-rs/object/pull/458) - -* The minimum supported rust version for the `write` feature has changed to 1.61.0. - -* Fixed endian handling in `read::elf::SymbolTable::shndx`. - [#458](https://github.com/gimli-rs/object/pull/458) - -* Fixed endian handling in `read::pe::ResourceName`. - [#458](https://github.com/gimli-rs/object/pull/458) - -* Changed definitions for LoongArch ELF header flags. - [#483](https://github.com/gimli-rs/object/pull/483) - -### Changed - -* Fixed parsing of multiple debug directory entries in `read::pe::PeFile::pdb_info`. - [#451](https://github.com/gimli-rs/object/pull/451) - -* Changed the section name used when writing COFF stub symbols. - [#475](https://github.com/gimli-rs/object/pull/475) - -### Added - -* Added `read::pe::DataDirectories::delay_load_import_table`. - [#448](https://github.com/gimli-rs/object/pull/448) - -* Added `read::macho::LoadCommandData::raw_data`. - [#449](https://github.com/gimli-rs/object/pull/449) - -* Added ELF relocations for LoongArch ps ABI v2. - [#450](https://github.com/gimli-rs/object/pull/450) - -* Added PowerPC support for Mach-O. - [#460](https://github.com/gimli-rs/object/pull/460) - -* Added support for reading the AIX big archive format. - [#462](https://github.com/gimli-rs/object/pull/462) - [#467](https://github.com/gimli-rs/object/pull/467) - [#473](https://github.com/gimli-rs/object/pull/473) - -* Added support for `RelocationEncoding::AArch64Call` when writing Mach-O files. - [#465](https://github.com/gimli-rs/object/pull/465) - -* Added support for `RelocationKind::Relative` when writing RISC-V ELF files. - [#470](https://github.com/gimli-rs/object/pull/470) - -* Added Xtensa architecture support for ELF. - [#481](https://github.com/gimli-rs/object/pull/481) - -* Added `read::pe::ResourceName::raw_data`. - [#487](https://github.com/gimli-rs/object/pull/487) - --------------------------------------------------------------------------------- - -## 0.29.0 - -Released 2022/06/22. - -### Breaking changes - -* The `write` feature now has a minimum supported rust version of 1.56.1. - [#444](https://github.com/gimli-rs/object/pull/444) - -* Added `os_abi` and `abi_version` fields to `FileFlags::Elf`. - [#438](https://github.com/gimli-rs/object/pull/438) - [#441](https://github.com/gimli-rs/object/pull/441) - -### Changed - -* Fixed handling of empty symbol tables in `read::elf::ElfFile::symbol_table` and - `read::elf::ElfFile::dynamic_symbol_table`. - [#443](https://github.com/gimli-rs/object/pull/443) - -### Added - -* Added more `ELF_OSABI_*` constants. - [#439](https://github.com/gimli-rs/object/pull/439) - --------------------------------------------------------------------------------- - -## 0.28.4 - -Released 2022/05/09. - -### Added - -* Added `read::pe::DataDirectories::resource_directory`. - [#425](https://github.com/gimli-rs/object/pull/425) - [#427](https://github.com/gimli-rs/object/pull/427) - -* Added PE support for more ARM relocations. - [#428](https://github.com/gimli-rs/object/pull/428) - -* Added support for `Architecture::LoongArch64`. - [#430](https://github.com/gimli-rs/object/pull/430) - [#432](https://github.com/gimli-rs/object/pull/432) - -* Added `elf::EF_MIPS_ABI` and associated constants. - [#433](https://github.com/gimli-rs/object/pull/433) - --------------------------------------------------------------------------------- - -## 0.28.3 - -Released 2022/01/19. - -### Changed - -* For the Mach-O support in `write::Object`, accept `RelocationKind::MachO` for all - architectures, and accept `RelocationKind::Absolute` for ARM64. - [#422](https://github.com/gimli-rs/object/pull/422) - -### Added - -* Added `pe::ImageDataDirectory::file_range`, `read::pe::SectionTable::pe_file_range_at` - and `pe::ImageSectionHeader::pe_file_range_at`. - [#421](https://github.com/gimli-rs/object/pull/421) - -* Added `write::Object::add_coff_exports`. - [#423](https://github.com/gimli-rs/object/pull/423) - --------------------------------------------------------------------------------- - -## 0.28.2 - -Released 2022/01/09. - -### Changed - -* Ignored errors for the Wasm extended name section in `read::WasmFile::parse`. - [#408](https://github.com/gimli-rs/object/pull/408) - -* Ignored errors for the COFF symbol table in `read::PeFile::parse`. - [#410](https://github.com/gimli-rs/object/pull/410) - -* Fixed handling of `SectionFlags::Coff` in `write::Object::coff_write`. - [#412](https://github.com/gimli-rs/object/pull/412) - -### Added - -* Added `read::ObjectSegment::flags`. - [#416](https://github.com/gimli-rs/object/pull/416) - [#418](https://github.com/gimli-rs/object/pull/418) - --------------------------------------------------------------------------------- - -## 0.28.1 - -Released 2021/12/12. - -### Changed - -* Fixed `read::elf::SymbolTable::shndx_section`. - [#405](https://github.com/gimli-rs/object/pull/405) - -* Fixed build warnings. - [#405](https://github.com/gimli-rs/object/pull/405) - [#406](https://github.com/gimli-rs/object/pull/406) - --------------------------------------------------------------------------------- - -## 0.28.0 - -Released 2021/12/12. - -### Breaking changes - -* `write_core` feature no longer enables `std` support. Use `write_std` instead. - [#400](https://github.com/gimli-rs/object/pull/400) - -* Multiple changes related to Mach-O split dyld cache support. - [#398](https://github.com/gimli-rs/object/pull/398) - -### Added - -* Added `write::pe::Writer::write_file_align`. - [#397](https://github.com/gimli-rs/object/pull/397) - -* Added support for Mach-O split dyld cache. - [#398](https://github.com/gimli-rs/object/pull/398) - -* Added support for `IMAGE_SCN_LNK_NRELOC_OVFL` when reading and writing COFF. - [#399](https://github.com/gimli-rs/object/pull/399) - -* Added `write::elf::Writer::reserve_null_symbol_index`. - [#402](https://github.com/gimli-rs/object/pull/402) - --------------------------------------------------------------------------------- - -## 0.27.1 - -Released 2021/10/22. - -### Changed - -* Fixed build error with older Rust versions due to cargo resolver version. - --------------------------------------------------------------------------------- - -## 0.27.0 - -Released 2021/10/17. - -### Breaking changes - -* Changed `read::elf` to use `SectionIndex` instead of `usize` in more places. - [#341](https://github.com/gimli-rs/object/pull/341) - -* Changed some `read::elf` section methods to additionally return the linked section index. - [#341](https://github.com/gimli-rs/object/pull/341) - -* Changed `read::pe::ImageNtHeaders::parse` to return `DataDirectories` instead of a slice. - [#357](https://github.com/gimli-rs/object/pull/357) - -* Deleted `value` parameter for `write:WritableBuffer::resize`. - [#369](https://github.com/gimli-rs/object/pull/369) - -* Changed `write::Object` and `write::Section` to use `Cow` for section data. - This added a lifetime parameter, which existing users can set to `'static`. - [#370](https://github.com/gimli-rs/object/pull/370) - -### Changed - -* Fixed parsing when PE import directory has zero size. - [#341](https://github.com/gimli-rs/object/pull/341) - -* Fixed parsing when PE import directory has zero for original first thunk. - [#385](https://github.com/gimli-rs/object/pull/385) - [#387](https://github.com/gimli-rs/object/pull/387) - -* Fixed parsing when PE export directory has zero number of names. - [#353](https://github.com/gimli-rs/object/pull/353) - -* Fixed parsing when PE export directory has zero number of names and addresses. - [#362](https://github.com/gimli-rs/object/pull/362) - -* Fixed parsing when PE sections are contiguous. - [#354](https://github.com/gimli-rs/object/pull/354) - -* Fixed `std` feature for `indexmap` dependency. - [#374](https://github.com/gimli-rs/object/pull/374) - -* Fixed overflow in COFF section name offset parsing. - [#390](https://github.com/gimli-rs/object/pull/390) - -### Added - -* Added `name_bytes` methods to unified `read` traits. - [#351](https://github.com/gimli-rs/object/pull/351) - -* Added `read::Object::kind`. - [#352](https://github.com/gimli-rs/object/pull/352) - -* Added `read::elf::VersionTable` and related helpers. - [#341](https://github.com/gimli-rs/object/pull/341) - -* Added `read::elf::SectionTable::dynamic` and related helpers. - [#345](https://github.com/gimli-rs/object/pull/345) - -* Added `read::coff::SectionTable::max_section_file_offset`. - [#344](https://github.com/gimli-rs/object/pull/344) - -* Added `read::pe::ExportTable` and related helpers. - [#349](https://github.com/gimli-rs/object/pull/349) - [#353](https://github.com/gimli-rs/object/pull/353) - -* Added `read::pe::ImportTable` and related helpers. - [#357](https://github.com/gimli-rs/object/pull/357) - -* Added `read::pe::DataDirectories` and related helpers. - [#357](https://github.com/gimli-rs/object/pull/357) - [#384](https://github.com/gimli-rs/object/pull/384) - -* Added `read::pe::RichHeaderInfo` and related helpers. - [#375](https://github.com/gimli-rs/object/pull/375) - [#379](https://github.com/gimli-rs/object/pull/379) - -* Added `read::pe::RelocationBlocks` and related helpers. - [#378](https://github.com/gimli-rs/object/pull/378) - -* Added `write::elf::Writer`. - [#350](https://github.com/gimli-rs/object/pull/350) - -* Added `write::pe::Writer`. - [#382](https://github.com/gimli-rs/object/pull/382) - [#388](https://github.com/gimli-rs/object/pull/388) - -* Added `write::Section::data/data_mut`. - [#367](https://github.com/gimli-rs/object/pull/367) - -* Added `write::Object::write_stream`. - [#369](https://github.com/gimli-rs/object/pull/369) - -* Added MIPSr6 ELF header flag definitions. - [#372](https://github.com/gimli-rs/object/pull/372) - --------------------------------------------------------------------------------- - -## 0.26.2 - -Released 2021/08/28. - -### Added - -* Added support for 64-bit symbol table names to `read::archive`. - [#366](https://github.com/gimli-rs/object/pull/366) - --------------------------------------------------------------------------------- - -## 0.26.1 - -Released 2021/08/19. - -### Changed - -* Activate `memchr`'s `rustc-dep-of-std` feature - [#356](https://github.com/gimli-rs/object/pull/356) - --------------------------------------------------------------------------------- - -## 0.26.0 - -Released 2021/07/26. - -### Breaking changes - -* Changed `ReadRef::read_bytes_at_until` to accept a range parameter. - [#326](https://github.com/gimli-rs/object/pull/326) - -* Added `ReadRef` type parameter to `read::StringTable` and types that - contain it. String table entries are now only read as required. - [#326](https://github.com/gimli-rs/object/pull/326) - -* Changed result type of `read::elf::SectionHeader::data` and `data_as_array`. - [#332](https://github.com/gimli-rs/object/pull/332) - -* Moved `pod::WritableBuffer` to `write::WritableBuffer`. - Renamed `WritableBuffer::extend` to `write_bytes`. - Added more provided methods to `WritableBuffer`. - [#335](https://github.com/gimli-rs/object/pull/335) - -* Moved `pod::Bytes` to `read::Bytes`. - [#336](https://github.com/gimli-rs/object/pull/336) - -* Added `is_mips64el` parameter to `elf::Rela64::r_info/set_r_info`. - [#337](https://github.com/gimli-rs/object/pull/337) - -### Changed - -* Removed `alloc` dependency when no features are enabled. - [#336](https://github.com/gimli-rs/object/pull/336) - -### Added - -* Added `read::pe::PeFile` methods: `section_table`, `data_directory`, and `data`. - [#324](https://github.com/gimli-rs/object/pull/324) - -* Added more ELF definitions. - [#332](https://github.com/gimli-rs/object/pull/332) - -* Added `read::elf::SectionTable` methods for hash tables and symbol version - information. - [#332](https://github.com/gimli-rs/object/pull/332) - -* Added PE RISC-V definitions. - [#333](https://github.com/gimli-rs/object/pull/333) - -* Added `WritableBuffer` implementation for `Vec`. - [#335](https://github.com/gimli-rs/object/pull/335) - --------------------------------------------------------------------------------- - -## 0.25.3 - -Released 2021/06/12. - -### Added - -* Added `RelocationEncoding::AArch64Call`. - [#322](https://github.com/gimli-rs/object/pull/322) - --------------------------------------------------------------------------------- - -## 0.25.2 - -Released 2021/06/04. - -### Added - -* Added `Architecture::X86_64_X32`. - [#320](https://github.com/gimli-rs/object/pull/320) - --------------------------------------------------------------------------------- - -## 0.25.1 - -Released 2021/06/03. - -### Changed - -* write: Fix choice of `SHT_REL` or `SHT_RELA` for most architectures. - [#318](https://github.com/gimli-rs/object/pull/318) - -* write: Fix relocation encoding for MIPS64EL. - [#318](https://github.com/gimli-rs/object/pull/318) - --------------------------------------------------------------------------------- - -## 0.25.0 - -Released 2021/06/02. - -### Breaking changes - -* Added `non_exhaustive` to most public enums. - [#306](https://github.com/gimli-rs/object/pull/306) - -* `MachHeader::parse` and `MachHeader::load_commands` now require a header offset. - [#304](https://github.com/gimli-rs/object/pull/304) - -* Added `ReadRef::read_bytes_at_until`. - [#308](https://github.com/gimli-rs/object/pull/308) - -* `PeFile::entry`, `PeSection::address` and `PeSegment::address` now return a - virtual address instead of a RVA. - [#315](https://github.com/gimli-rs/object/pull/315) - -### Added - -* Added `pod::from_bytes_mut`, `pod::slice_from_bytes_mut`, `pod::bytes_of_mut`, - and `pod::bytes_of_slice_mut`. - [#296](https://github.com/gimli-rs/object/pull/296) - [#297](https://github.com/gimli-rs/object/pull/297) - -* Added `Object::pdb_info`. - [#298](https://github.com/gimli-rs/object/pull/298) - -* Added `read::macho::DyldCache`, other associated definitions, - and support for these in the examples. - [#308](https://github.com/gimli-rs/object/pull/308) - -* Added more architecture support. - [#303](https://github.com/gimli-rs/object/pull/303) - [#309](https://github.com/gimli-rs/object/pull/309) - -* Derive more traits for enums. - [#311](https://github.com/gimli-rs/object/pull/311) - -* Added `Object::relative_address_base`. - [#315](https://github.com/gimli-rs/object/pull/315) - -### Changed - -* Improved performance for string parsing. - [#302](https://github.com/gimli-rs/object/pull/302) - -* `objdump` example allows selecting container members. - [#308](https://github.com/gimli-rs/object/pull/308) diff --git a/vendor/object/Cargo.toml b/vendor/object/Cargo.toml deleted file mode 100644 index c408ae5..0000000 --- a/vendor/object/Cargo.toml +++ /dev/null @@ -1,163 +0,0 @@ -# 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 = "object" -version = "0.32.2" -exclude = [ - "/.github", - "/testfiles", -] -description = "A unified interface for reading and writing object file formats." -readme = "README.md" -keywords = [ - "object", - "elf", - "mach-o", - "pe", - "coff", -] -license = "Apache-2.0 OR MIT" -repository = "https://github.com/gimli-rs/object" -resolver = "2" - -[package.metadata.docs.rs] -features = ["doc"] - -[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.crc32fast] -version = "1.2" -optional = true -default-features = false - -[dependencies.flate2] -version = "1" -optional = true - -[dependencies.hashbrown] -version = "0.14.0" -features = ["ahash"] -optional = true -default-features = false - -[dependencies.indexmap] -version = "2.0" -optional = true -default-features = false - -[dependencies.memchr] -version = "2.4.1" -default-features = false - -[dependencies.ruzstd] -version = "0.5.0" -optional = true - -[dependencies.wasmparser] -version = "0.118.0" -optional = true - -[features] -all = [ - "read", - "write", - "std", - "compression", - "wasm", -] -archive = [] -cargo-all = [] -coff = [] -compression = [ - "dep:flate2", - "dep:ruzstd", - "std", -] -default = [ - "read", - "compression", -] -doc = [ - "read_core", - "write_std", - "std", - "compression", - "archive", - "coff", - "elf", - "macho", - "pe", - "wasm", - "xcoff", -] -elf = [] -macho = [] -pe = ["coff"] -read = [ - "read_core", - "archive", - "coff", - "elf", - "macho", - "pe", - "xcoff", - "unaligned", -] -read_core = [] -rustc-dep-of-std = [ - "core", - "compiler_builtins", - "alloc", - "memchr/rustc-dep-of-std", -] -std = ["memchr/std"] -unaligned = [] -unstable = [] -unstable-all = [ - "all", - "unstable", -] -wasm = ["dep:wasmparser"] -write = [ - "write_std", - "coff", - "elf", - "macho", - "pe", - "xcoff", -] -write_core = [ - "dep:crc32fast", - "dep:indexmap", - "dep:hashbrown", -] -write_std = [ - "write_core", - "std", - "indexmap?/std", - "crc32fast?/std", -] -xcoff = [] diff --git a/vendor/object/LICENSE-APACHE b/vendor/object/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/vendor/object/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - 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. diff --git a/vendor/object/LICENSE-MIT b/vendor/object/LICENSE-MIT deleted file mode 100644 index 8440c7e..0000000 --- a/vendor/object/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2015 The Gimli 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. diff --git a/vendor/object/README.md b/vendor/object/README.md deleted file mode 100644 index 08d9c80..0000000 --- a/vendor/object/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# `object` - -The `object` crate provides a unified interface to working with object files -across platforms. It supports reading relocatable object files and executable files, -and writing COFF/ELF/Mach-O/XCOFF relocatable object files and ELF/PE executable files. - -For reading files, it provides multiple levels of support: - -* raw struct definitions suitable for zero copy access -* low level APIs for accessing the raw structs ([example](crates/examples/src/readobj/)) -* a higher level unified API for accessing common features of object files, such - as sections and symbols ([example](crates/examples/src/objdump.rs)) - -Supported file formats: ELF, Mach-O, Windows PE/COFF, Wasm, XCOFF, and Unix archive. - -## Example for unified read API -```rust -use object::{Object, ObjectSection}; -use std::error::Error; -use std::fs; - -/// Reads a file and displays the name of each section. -fn main() -> Result<(), Box> { - let binary_data = fs::read("path/to/binary")?; - let file = object::File::parse(&*binary_data)?; - for section in file.sections() { - println!("{}", section.name()?); - } - Ok(()) -} -``` - -See [`crates/examples`](crates/examples) for more examples. - -## Minimum Supported Rust Version (MSRV) - -Changes to MSRV are considered breaking changes. We are conservative about changing the MSRV, -but sometimes are required to due to dependencies. The MSRV is: - - * 1.60.0 for the `read` feature and its dependencies. - * 1.65.0 for other features. - -## 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 - -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. diff --git a/vendor/object/clippy.toml b/vendor/object/clippy.toml deleted file mode 100644 index 16caf02..0000000 --- a/vendor/object/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -msrv = "1.60.0" diff --git a/vendor/object/src/archive.rs b/vendor/object/src/archive.rs deleted file mode 100644 index 6271d07..0000000 --- a/vendor/object/src/archive.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! Archive definitions. -//! -//! These definitions are independent of read/write support, although we do implement -//! some traits useful for those. - -use crate::pod::Pod; - -/// File identification bytes stored at the beginning of the file. -pub const MAGIC: [u8; 8] = *b"!\n"; - -/// File identification bytes at the beginning of AIX big archive. -pub const AIX_BIG_MAGIC: [u8; 8] = *b"\n"; - -/// File identification bytes stored at the beginning of a thin archive. -/// -/// A thin archive only contains a symbol table and file names. -pub const THIN_MAGIC: [u8; 8] = *b"!\n"; - -/// The terminator for each archive member header. -pub const TERMINATOR: [u8; 2] = *b"`\n"; - -/// The header at the start of an archive member. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Header { - /// The file name. - pub name: [u8; 16], - /// File modification timestamp in decimal. - pub date: [u8; 12], - /// User ID in decimal. - pub uid: [u8; 6], - /// Group ID in decimal. - pub gid: [u8; 6], - /// File mode in octal. - pub mode: [u8; 8], - /// File size in decimal. - pub size: [u8; 10], - /// Must be equal to `TERMINATOR`. - pub terminator: [u8; 2], -} - -/// The header at the start of an AIX big archive member, without name. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AixHeader { - /// File member size in decimal. - pub size: [u8; 20], - /// Next member offset in decimal. - pub nxtmem: [u8; 20], - /// Previous member offset in decimal. - pub prvmem: [u8; 20], - /// File member date in decimal. - pub date: [u8; 12], - /// File member user id in decimal. - pub uid: [u8; 12], - /// File member group id in decimal. - pub gid: [u8; 12], - /// File member mode in octal. - pub mode: [u8; 12], - /// File member name length in decimal. - pub namlen: [u8; 4], -} - -/// The AIX big archive's fixed length header at file beginning. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AixFileHeader { - /// Archive magic string. - pub magic: [u8; 8], - /// Offset of member table. - pub memoff: [u8; 20], - /// Offset of global symbol table. - pub gstoff: [u8; 20], - /// Offset of global symbol table for 64-bit objects. - pub gst64off: [u8; 20], - /// Offset of first member. - pub fstmoff: [u8; 20], - /// Offset of last member. - pub lstmoff: [u8; 20], - /// Offset of first member on free list. - pub freeoff: [u8; 20], -} - -/// Offset of a member in an AIX big archive. -/// -/// This is used in the member index. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AixMemberOffset(pub [u8; 20]); - -unsafe_impl_pod!(Header, AixHeader, AixFileHeader, AixMemberOffset,); diff --git a/vendor/object/src/common.rs b/vendor/object/src/common.rs deleted file mode 100644 index 36f6656..0000000 --- a/vendor/object/src/common.rs +++ /dev/null @@ -1,536 +0,0 @@ -/// A CPU architecture. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum Architecture { - Unknown, - Aarch64, - #[allow(non_camel_case_types)] - Aarch64_Ilp32, - Arm, - Avr, - Bpf, - Csky, - I386, - X86_64, - #[allow(non_camel_case_types)] - X86_64_X32, - Hexagon, - LoongArch64, - Mips, - Mips64, - Msp430, - PowerPc, - PowerPc64, - Riscv32, - Riscv64, - S390x, - Sbf, - Sharc, - Sparc64, - Wasm32, - Wasm64, - Xtensa, -} - -/// A CPU sub-architecture. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SubArchitecture { - Arm64E, - Arm64EC, -} - -impl Architecture { - /// The size of an address value for this architecture. - /// - /// Returns `None` for unknown architectures. - pub fn address_size(self) -> Option { - match self { - Architecture::Unknown => None, - Architecture::Aarch64 => Some(AddressSize::U64), - Architecture::Aarch64_Ilp32 => Some(AddressSize::U32), - Architecture::Arm => Some(AddressSize::U32), - Architecture::Avr => Some(AddressSize::U8), - Architecture::Bpf => Some(AddressSize::U64), - Architecture::Csky => Some(AddressSize::U32), - Architecture::I386 => Some(AddressSize::U32), - Architecture::X86_64 => Some(AddressSize::U64), - Architecture::X86_64_X32 => Some(AddressSize::U32), - Architecture::Hexagon => Some(AddressSize::U32), - Architecture::LoongArch64 => Some(AddressSize::U64), - Architecture::Mips => Some(AddressSize::U32), - Architecture::Mips64 => Some(AddressSize::U64), - Architecture::Msp430 => Some(AddressSize::U16), - Architecture::PowerPc => Some(AddressSize::U32), - Architecture::PowerPc64 => Some(AddressSize::U64), - Architecture::Riscv32 => Some(AddressSize::U32), - Architecture::Riscv64 => Some(AddressSize::U64), - Architecture::S390x => Some(AddressSize::U64), - Architecture::Sbf => Some(AddressSize::U64), - Architecture::Sharc => Some(AddressSize::U32), - Architecture::Sparc64 => Some(AddressSize::U64), - Architecture::Wasm32 => Some(AddressSize::U32), - Architecture::Wasm64 => Some(AddressSize::U64), - Architecture::Xtensa => Some(AddressSize::U32), - } - } -} - -/// The size of an address value for an architecture. -/// -/// This may differ from the address size supported by the file format (such as for COFF). -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -#[repr(u8)] -pub enum AddressSize { - U8 = 1, - U16 = 2, - U32 = 4, - U64 = 8, -} - -impl AddressSize { - /// The size in bytes of an address value. - #[inline] - pub fn bytes(self) -> u8 { - self as u8 - } -} - -/// A binary file format. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum BinaryFormat { - Coff, - Elf, - MachO, - Pe, - Wasm, - Xcoff, -} - -/// The kind of a section. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SectionKind { - /// The section kind is unknown. - Unknown, - /// An executable code section. - /// - /// Example ELF sections: `.text` - /// - /// Example Mach-O sections: `__TEXT/__text` - Text, - /// A data section. - /// - /// Example ELF sections: `.data` - /// - /// Example Mach-O sections: `__DATA/__data` - Data, - /// A read only data section. - /// - /// Example ELF sections: `.rodata` - /// - /// Example Mach-O sections: `__TEXT/__const`, `__DATA/__const`, `__TEXT/__literal4` - ReadOnlyData, - /// A read only data section with relocations. - /// - /// This is the same as either `Data` or `ReadOnlyData`, depending on the file format. - /// This value is only used in the API for writing files. It is never returned when reading files. - ReadOnlyDataWithRel, - /// A loadable string section. - /// - /// Example ELF sections: `.rodata.str` - /// - /// Example Mach-O sections: `__TEXT/__cstring` - ReadOnlyString, - /// An uninitialized data section. - /// - /// Example ELF sections: `.bss` - /// - /// Example Mach-O sections: `__DATA/__bss` - UninitializedData, - /// An uninitialized common data section. - /// - /// Example Mach-O sections: `__DATA/__common` - Common, - /// A TLS data section. - /// - /// Example ELF sections: `.tdata` - /// - /// Example Mach-O sections: `__DATA/__thread_data` - Tls, - /// An uninitialized TLS data section. - /// - /// Example ELF sections: `.tbss` - /// - /// Example Mach-O sections: `__DATA/__thread_bss` - UninitializedTls, - /// A TLS variables section. - /// - /// This contains TLS variable structures, rather than the variable initializers. - /// - /// Example Mach-O sections: `__DATA/__thread_vars` - TlsVariables, - /// A non-loadable string section. - /// - /// Example ELF sections: `.comment`, `.debug_str` - OtherString, - /// Some other non-loadable section. - /// - /// Example ELF sections: `.debug_info` - Other, - /// Debug information. - /// - /// Example Mach-O sections: `__DWARF/__debug_info` - Debug, - /// Information for the linker. - /// - /// Example COFF sections: `.drectve` - Linker, - /// ELF note section. - Note, - /// Metadata such as symbols or relocations. - /// - /// Example ELF sections: `.symtab`, `.strtab`, `.group` - Metadata, - /// Some other ELF section type. - /// - /// This is the `sh_type` field in the section header. - /// The meaning may be dependent on the architecture. - Elf(u32), -} - -impl SectionKind { - /// Return true if this section contains zerofill data. - pub fn is_bss(self) -> bool { - self == SectionKind::UninitializedData - || self == SectionKind::UninitializedTls - || self == SectionKind::Common - } -} - -/// The selection kind for a COMDAT section group. -/// -/// This determines the way in which the linker resolves multiple definitions of the COMDAT -/// sections. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ComdatKind { - /// The selection kind is unknown. - Unknown, - /// Multiple definitions are allowed. - /// - /// An arbitrary definition is selected, and the rest are removed. - /// - /// This is the only supported selection kind for ELF. - Any, - /// Multiple definitions are not allowed. - /// - /// This is used to group sections without allowing duplicates. - NoDuplicates, - /// Multiple definitions must have the same size. - /// - /// An arbitrary definition is selected, and the rest are removed. - SameSize, - /// Multiple definitions must match exactly. - /// - /// An arbitrary definition is selected, and the rest are removed. - ExactMatch, - /// Multiple definitions are allowed, and the largest is selected. - /// - /// An arbitrary definition with the largest size is selected, and the rest are removed. - Largest, - /// Multiple definitions are allowed, and the newest is selected. - Newest, -} - -/// The kind of a symbol. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SymbolKind { - /// The symbol kind is unknown. - Unknown, - /// The symbol is a null placeholder. - Null, - /// The symbol is for executable code. - Text, - /// The symbol is for a data object. - Data, - /// The symbol is for a section. - Section, - /// The symbol is the name of a file. It precedes symbols within that file. - File, - /// The symbol is for a code label. - Label, - /// The symbol is for a thread local storage entity. - Tls, -} - -/// A symbol scope. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum SymbolScope { - /// Unknown scope. - Unknown, - /// Symbol is visible to the compilation unit. - Compilation, - /// Symbol is visible to the static linkage unit. - Linkage, - /// Symbol is visible to dynamically linked objects. - Dynamic, -} - -/// The operation used to calculate the result of the relocation. -/// -/// The relocation descriptions use the following definitions. Note that -/// these definitions probably don't match any ELF ABI. -/// -/// * A - The value of the addend. -/// * G - The address of the symbol's entry within the global offset table. -/// * L - The address of the symbol's entry within the procedure linkage table. -/// * P - The address of the place of the relocation. -/// * S - The address of the symbol. -/// * GotBase - The address of the global offset table. -/// * Image - The base address of the image. -/// * Section - The address of the section containing the symbol. -/// -/// 'XxxRelative' means 'Xxx + A - P'. 'XxxOffset' means 'S + A - Xxx'. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum RelocationKind { - /// S + A - Absolute, - /// S + A - P - Relative, - /// G + A - GotBase - Got, - /// G + A - P - GotRelative, - /// GotBase + A - P - GotBaseRelative, - /// S + A - GotBase - GotBaseOffset, - /// L + A - P - PltRelative, - /// S + A - Image - ImageOffset, - /// S + A - Section - SectionOffset, - /// The index of the section containing the symbol. - SectionIndex, - /// Some other ELF relocation. The value is dependent on the architecture. - Elf(u32), - /// Some other Mach-O relocation. The value is dependent on the architecture. - MachO { - /// The relocation type. - value: u8, - /// Whether the relocation is relative to the place. - relative: bool, - }, - /// Some other COFF relocation. The value is dependent on the architecture. - Coff(u16), - /// Some other XCOFF relocation. - Xcoff(u8), -} - -/// Information about how the result of the relocation operation is encoded in the place. -/// -/// This is usually architecture specific, such as specifying an addressing mode or -/// a specific instruction. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum RelocationEncoding { - /// Generic encoding. - Generic, - - /// x86 sign extension at runtime. - /// - /// Used with `RelocationKind::Absolute`. - X86Signed, - /// x86 rip-relative addressing. - /// - /// The `RelocationKind` must be PC relative. - X86RipRelative, - /// x86 rip-relative addressing in movq instruction. - /// - /// The `RelocationKind` must be PC relative. - X86RipRelativeMovq, - /// x86 branch instruction. - /// - /// The `RelocationKind` must be PC relative. - X86Branch, - - /// s390x PC-relative offset shifted right by one bit. - /// - /// The `RelocationKind` must be PC relative. - S390xDbl, - - /// AArch64 call target. - /// - /// The `RelocationKind` must be PC relative. - AArch64Call, - - /// LoongArch branch offset with two trailing zeros. - /// - /// The `RelocationKind` must be PC relative. - LoongArchBranch, - - /// SHARC+ 48-bit Type A instruction - /// - /// Represents these possible variants, each with a corresponding - /// `R_SHARC_*` constant: - /// - /// * 24-bit absolute address - /// * 32-bit absolute address - /// * 6-bit relative address - /// * 24-bit relative address - /// * 6-bit absolute address in the immediate value field - /// * 16-bit absolute address in the immediate value field - SharcTypeA, - - /// SHARC+ 32-bit Type B instruction - /// - /// Represents these possible variants, each with a corresponding - /// `R_SHARC_*` constant: - /// - /// * 6-bit absolute address in the immediate value field - /// * 7-bit absolute address in the immediate value field - /// * 16-bit absolute address - /// * 6-bit relative address - SharcTypeB, -} - -/// File flags that are specific to each file format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum FileFlags { - /// No file flags. - None, - /// ELF file flags. - Elf { - /// `os_abi` field in the ELF file header. - os_abi: u8, - /// `abi_version` field in the ELF file header. - abi_version: u8, - /// `e_flags` field in the ELF file header. - e_flags: u32, - }, - /// Mach-O file flags. - MachO { - /// `flags` field in the Mach-O file header. - flags: u32, - }, - /// COFF file flags. - Coff { - /// `Characteristics` field in the COFF file header. - characteristics: u16, - }, - /// XCOFF file flags. - Xcoff { - /// `f_flags` field in the XCOFF file header. - f_flags: u16, - }, -} - -/// Segment flags that are specific to each file format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SegmentFlags { - /// No segment flags. - None, - /// ELF segment flags. - Elf { - /// `p_flags` field in the segment header. - p_flags: u32, - }, - /// Mach-O segment flags. - MachO { - /// `flags` field in the segment header. - flags: u32, - /// `maxprot` field in the segment header. - maxprot: u32, - /// `initprot` field in the segment header. - initprot: u32, - }, - /// COFF segment flags. - Coff { - /// `Characteristics` field in the segment header. - characteristics: u32, - }, -} - -/// Section flags that are specific to each file format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SectionFlags { - /// No section flags. - None, - /// ELF section flags. - Elf { - /// `sh_flags` field in the section header. - sh_flags: u64, - }, - /// Mach-O section flags. - MachO { - /// `flags` field in the section header. - flags: u32, - }, - /// COFF section flags. - Coff { - /// `Characteristics` field in the section header. - characteristics: u32, - }, - /// XCOFF section flags. - Xcoff { - /// `s_flags` field in the section header. - s_flags: u32, - }, -} - -/// Symbol flags that are specific to each file format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SymbolFlags { - /// No symbol flags. - None, - /// ELF symbol flags. - Elf { - /// `st_info` field in the ELF symbol. - st_info: u8, - /// `st_other` field in the ELF symbol. - st_other: u8, - }, - /// Mach-O symbol flags. - MachO { - /// `n_desc` field in the Mach-O symbol. - n_desc: u16, - }, - /// COFF flags for a section symbol. - CoffSection { - /// `Selection` field in the auxiliary symbol for the section. - selection: u8, - /// `Number` field in the auxiliary symbol for the section. - associative_section: Option
, - }, - /// XCOFF symbol flags. - Xcoff { - /// `n_sclass` field in the XCOFF symbol. - n_sclass: u8, - /// `x_smtyp` field in the CSECT auxiliary symbol. - /// - /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`. - x_smtyp: u8, - /// `x_smclas` field in the CSECT auxiliary symbol. - /// - /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`. - x_smclas: u8, - /// The containing csect for the symbol. - /// - /// Only valid if `x_smtyp` is `XTY_LD`. - containing_csect: Option, - }, -} diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs deleted file mode 100644 index f620171..0000000 --- a/vendor/object/src/elf.rs +++ /dev/null @@ -1,6287 +0,0 @@ -//! ELF definitions. -//! -//! These definitions are independent of read/write support, although we do implement -//! some traits useful for those. -//! -//! This module is the equivalent of /usr/include/elf.h, and is based heavily on it. - -#![allow(missing_docs)] -#![allow(clippy::identity_op)] - -use crate::endian::{Endian, U32Bytes, U64Bytes, I32, I64, U16, U32, U64}; -use crate::pod::Pod; - -/// The header at the start of every 32-bit ELF file. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileHeader32 { - /// Magic number and other information. - pub e_ident: Ident, - /// Object file type. One of the `ET_*` constants. - pub e_type: U16, - /// Architecture. One of the `EM_*` constants. - pub e_machine: U16, - /// Object file version. Must be `EV_CURRENT`. - pub e_version: U32, - /// Entry point virtual address. - pub e_entry: U32, - /// Program header table file offset. - pub e_phoff: U32, - /// Section header table file offset. - pub e_shoff: U32, - /// Processor-specific flags. - /// - /// A combination of the `EF_*` constants. - pub e_flags: U32, - /// Size in bytes of this header. - pub e_ehsize: U16, - /// Program header table entry size. - pub e_phentsize: U16, - /// Program header table entry count. - /// - /// If the count is greater than or equal to `PN_XNUM` then this field is set to - /// `PN_XNUM` and the count is stored in the `sh_info` field of section 0. - pub e_phnum: U16, - /// Section header table entry size. - pub e_shentsize: U16, - /// Section header table entry count. - /// - /// If the count is greater than or equal to `SHN_LORESERVE` then this field is set to - /// `0` and the count is stored in the `sh_size` field of section 0. - /// first section header. - pub e_shnum: U16, - /// Section header string table index. - /// - /// If the index is greater than or equal to `SHN_LORESERVE` then this field is set to - /// `SHN_XINDEX` and the index is stored in the `sh_link` field of section 0. - pub e_shstrndx: U16, -} - -/// The header at the start of every 64-bit ELF file. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileHeader64 { - /// Magic number and other information. - pub e_ident: Ident, - /// Object file type. One of the `ET_*` constants. - pub e_type: U16, - /// Architecture. One of the `EM_*` constants. - pub e_machine: U16, - /// Object file version. Must be `EV_CURRENT`. - pub e_version: U32, - /// Entry point virtual address. - pub e_entry: U64, - /// Program header table file offset. - pub e_phoff: U64, - /// Section header table file offset. - pub e_shoff: U64, - /// Processor-specific flags. - /// - /// A combination of the `EF_*` constants. - pub e_flags: U32, - /// Size in bytes of this header. - pub e_ehsize: U16, - /// Program header table entry size. - pub e_phentsize: U16, - /// Program header table entry count. - /// - /// If the count is greater than or equal to `PN_XNUM` then this field is set to - /// `PN_XNUM` and the count is stored in the `sh_info` field of section 0. - pub e_phnum: U16, - /// Section header table entry size. - pub e_shentsize: U16, - /// Section header table entry count. - /// - /// If the count is greater than or equal to `SHN_LORESERVE` then this field is set to - /// `0` and the count is stored in the `sh_size` field of section 0. - /// first section header. - pub e_shnum: U16, - /// Section header string table index. - /// - /// If the index is greater than or equal to `SHN_LORESERVE` then this field is set to - /// `SHN_XINDEX` and the index is stored in the `sh_link` field of section 0. - pub e_shstrndx: U16, -} - -/// Magic number and other information. -/// -/// Contained in the file header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Ident { - /// Magic number. Must be `ELFMAG`. - pub magic: [u8; 4], - /// File class. One of the `ELFCLASS*` constants. - pub class: u8, - /// Data encoding. One of the `ELFDATA*` constants. - pub data: u8, - /// ELF version. Must be `EV_CURRENT`. - pub version: u8, - /// OS ABI identification. One of the `ELFOSABI*` constants. - pub os_abi: u8, - /// ABI version. - /// - /// The meaning of this field depends on the `os_abi` value. - pub abi_version: u8, - /// Padding bytes. - pub padding: [u8; 7], -} - -/// File identification bytes stored in `Ident::magic`. -pub const ELFMAG: [u8; 4] = [0x7f, b'E', b'L', b'F']; - -// Values for `Ident::class`. -/// Invalid class. -pub const ELFCLASSNONE: u8 = 0; -/// 32-bit object. -pub const ELFCLASS32: u8 = 1; -/// 64-bit object. -pub const ELFCLASS64: u8 = 2; - -// Values for `Ident::data`. -/// Invalid data encoding. -pub const ELFDATANONE: u8 = 0; -/// 2's complement, little endian. -pub const ELFDATA2LSB: u8 = 1; -/// 2's complement, big endian. -pub const ELFDATA2MSB: u8 = 2; - -// Values for `Ident::os_abi`. -/// UNIX System V ABI. -pub const ELFOSABI_NONE: u8 = 0; -/// UNIX System V ABI. -/// -/// Alias. -pub const ELFOSABI_SYSV: u8 = 0; -/// HP-UX. -pub const ELFOSABI_HPUX: u8 = 1; -/// NetBSD. -pub const ELFOSABI_NETBSD: u8 = 2; -/// Object uses GNU ELF extensions. -pub const ELFOSABI_GNU: u8 = 3; -/// Object uses GNU ELF extensions. -/// -/// Compatibility alias. -pub const ELFOSABI_LINUX: u8 = ELFOSABI_GNU; -/// GNU/Hurd. -pub const ELFOSABI_HURD: u8 = 4; -/// Sun Solaris. -pub const ELFOSABI_SOLARIS: u8 = 6; -/// IBM AIX. -pub const ELFOSABI_AIX: u8 = 7; -/// SGI Irix. -pub const ELFOSABI_IRIX: u8 = 8; -/// FreeBSD. -pub const ELFOSABI_FREEBSD: u8 = 9; -/// Compaq TRU64 UNIX. -pub const ELFOSABI_TRU64: u8 = 10; -/// Novell Modesto. -pub const ELFOSABI_MODESTO: u8 = 11; -/// OpenBSD. -pub const ELFOSABI_OPENBSD: u8 = 12; -/// OpenVMS. -pub const ELFOSABI_OPENVMS: u8 = 13; -/// Hewlett-Packard Non-Stop Kernel. -pub const ELFOSABI_NSK: u8 = 14; -/// AROS -pub const ELFOSABI_AROS: u8 = 15; -/// FenixOS -pub const ELFOSABI_FENIXOS: u8 = 16; -/// Nuxi CloudABI -pub const ELFOSABI_CLOUDABI: u8 = 17; -/// ARM EABI. -pub const ELFOSABI_ARM_AEABI: u8 = 64; -/// ARM. -pub const ELFOSABI_ARM: u8 = 97; -/// Standalone (embedded) application. -pub const ELFOSABI_STANDALONE: u8 = 255; - -// Values for `FileHeader*::e_type`. -/// No file type. -pub const ET_NONE: u16 = 0; -/// Relocatable file. -pub const ET_REL: u16 = 1; -/// Executable file. -pub const ET_EXEC: u16 = 2; -/// Shared object file. -pub const ET_DYN: u16 = 3; -/// Core file. -pub const ET_CORE: u16 = 4; -/// OS-specific range start. -pub const ET_LOOS: u16 = 0xfe00; -/// OS-specific range end. -pub const ET_HIOS: u16 = 0xfeff; -/// Processor-specific range start. -pub const ET_LOPROC: u16 = 0xff00; -/// Processor-specific range end. -pub const ET_HIPROC: u16 = 0xffff; - -// Values for `FileHeader*::e_machine`. -/// No machine -pub const EM_NONE: u16 = 0; -/// AT&T WE 32100 -pub const EM_M32: u16 = 1; -/// SUN SPARC -pub const EM_SPARC: u16 = 2; -/// Intel 80386 -pub const EM_386: u16 = 3; -/// Motorola m68k family -pub const EM_68K: u16 = 4; -/// Motorola m88k family -pub const EM_88K: u16 = 5; -/// Intel MCU -pub const EM_IAMCU: u16 = 6; -/// Intel 80860 -pub const EM_860: u16 = 7; -/// MIPS R3000 big-endian -pub const EM_MIPS: u16 = 8; -/// IBM System/370 -pub const EM_S370: u16 = 9; -/// MIPS R3000 little-endian -pub const EM_MIPS_RS3_LE: u16 = 10; -/// HPPA -pub const EM_PARISC: u16 = 15; -/// Fujitsu VPP500 -pub const EM_VPP500: u16 = 17; -/// Sun's "v8plus" -pub const EM_SPARC32PLUS: u16 = 18; -/// Intel 80960 -pub const EM_960: u16 = 19; -/// PowerPC -pub const EM_PPC: u16 = 20; -/// PowerPC 64-bit -pub const EM_PPC64: u16 = 21; -/// IBM S390 -pub const EM_S390: u16 = 22; -/// IBM SPU/SPC -pub const EM_SPU: u16 = 23; -/// NEC V800 series -pub const EM_V800: u16 = 36; -/// Fujitsu FR20 -pub const EM_FR20: u16 = 37; -/// TRW RH-32 -pub const EM_RH32: u16 = 38; -/// Motorola RCE -pub const EM_RCE: u16 = 39; -/// ARM -pub const EM_ARM: u16 = 40; -/// Digital Alpha -pub const EM_FAKE_ALPHA: u16 = 41; -/// Hitachi SH -pub const EM_SH: u16 = 42; -/// SPARC v9 64-bit -pub const EM_SPARCV9: u16 = 43; -/// Siemens Tricore -pub const EM_TRICORE: u16 = 44; -/// Argonaut RISC Core -pub const EM_ARC: u16 = 45; -/// Hitachi H8/300 -pub const EM_H8_300: u16 = 46; -/// Hitachi H8/300H -pub const EM_H8_300H: u16 = 47; -/// Hitachi H8S -pub const EM_H8S: u16 = 48; -/// Hitachi H8/500 -pub const EM_H8_500: u16 = 49; -/// Intel Merced -pub const EM_IA_64: u16 = 50; -/// Stanford MIPS-X -pub const EM_MIPS_X: u16 = 51; -/// Motorola Coldfire -pub const EM_COLDFIRE: u16 = 52; -/// Motorola M68HC12 -pub const EM_68HC12: u16 = 53; -/// Fujitsu MMA Multimedia Accelerator -pub const EM_MMA: u16 = 54; -/// Siemens PCP -pub const EM_PCP: u16 = 55; -/// Sony nCPU embeeded RISC -pub const EM_NCPU: u16 = 56; -/// Denso NDR1 microprocessor -pub const EM_NDR1: u16 = 57; -/// Motorola Start*Core processor -pub const EM_STARCORE: u16 = 58; -/// Toyota ME16 processor -pub const EM_ME16: u16 = 59; -/// STMicroelectronic ST100 processor -pub const EM_ST100: u16 = 60; -/// Advanced Logic Corp. Tinyj emb.fam -pub const EM_TINYJ: u16 = 61; -/// AMD x86-64 architecture -pub const EM_X86_64: u16 = 62; -/// Sony DSP Processor -pub const EM_PDSP: u16 = 63; -/// Digital PDP-10 -pub const EM_PDP10: u16 = 64; -/// Digital PDP-11 -pub const EM_PDP11: u16 = 65; -/// Siemens FX66 microcontroller -pub const EM_FX66: u16 = 66; -/// STMicroelectronics ST9+ 8/16 mc -pub const EM_ST9PLUS: u16 = 67; -/// STmicroelectronics ST7 8 bit mc -pub const EM_ST7: u16 = 68; -/// Motorola MC68HC16 microcontroller -pub const EM_68HC16: u16 = 69; -/// Motorola MC68HC11 microcontroller -pub const EM_68HC11: u16 = 70; -/// Motorola MC68HC08 microcontroller -pub const EM_68HC08: u16 = 71; -/// Motorola MC68HC05 microcontroller -pub const EM_68HC05: u16 = 72; -/// Silicon Graphics SVx -pub const EM_SVX: u16 = 73; -/// STMicroelectronics ST19 8 bit mc -pub const EM_ST19: u16 = 74; -/// Digital VAX -pub const EM_VAX: u16 = 75; -/// Axis Communications 32-bit emb.proc -pub const EM_CRIS: u16 = 76; -/// Infineon Technologies 32-bit emb.proc -pub const EM_JAVELIN: u16 = 77; -/// Element 14 64-bit DSP Processor -pub const EM_FIREPATH: u16 = 78; -/// LSI Logic 16-bit DSP Processor -pub const EM_ZSP: u16 = 79; -/// Donald Knuth's educational 64-bit proc -pub const EM_MMIX: u16 = 80; -/// Harvard University machine-independent object files -pub const EM_HUANY: u16 = 81; -/// SiTera Prism -pub const EM_PRISM: u16 = 82; -/// Atmel AVR 8-bit microcontroller -pub const EM_AVR: u16 = 83; -/// Fujitsu FR30 -pub const EM_FR30: u16 = 84; -/// Mitsubishi D10V -pub const EM_D10V: u16 = 85; -/// Mitsubishi D30V -pub const EM_D30V: u16 = 86; -/// NEC v850 -pub const EM_V850: u16 = 87; -/// Mitsubishi M32R -pub const EM_M32R: u16 = 88; -/// Matsushita MN10300 -pub const EM_MN10300: u16 = 89; -/// Matsushita MN10200 -pub const EM_MN10200: u16 = 90; -/// picoJava -pub const EM_PJ: u16 = 91; -/// OpenRISC 32-bit embedded processor -pub const EM_OPENRISC: u16 = 92; -/// ARC International ARCompact -pub const EM_ARC_COMPACT: u16 = 93; -/// Tensilica Xtensa Architecture -pub const EM_XTENSA: u16 = 94; -/// Alphamosaic VideoCore -pub const EM_VIDEOCORE: u16 = 95; -/// Thompson Multimedia General Purpose Proc -pub const EM_TMM_GPP: u16 = 96; -/// National Semi. 32000 -pub const EM_NS32K: u16 = 97; -/// Tenor Network TPC -pub const EM_TPC: u16 = 98; -/// Trebia SNP 1000 -pub const EM_SNP1K: u16 = 99; -/// STMicroelectronics ST200 -pub const EM_ST200: u16 = 100; -/// Ubicom IP2xxx -pub const EM_IP2K: u16 = 101; -/// MAX processor -pub const EM_MAX: u16 = 102; -/// National Semi. CompactRISC -pub const EM_CR: u16 = 103; -/// Fujitsu F2MC16 -pub const EM_F2MC16: u16 = 104; -/// Texas Instruments msp430 -pub const EM_MSP430: u16 = 105; -/// Analog Devices Blackfin DSP -pub const EM_BLACKFIN: u16 = 106; -/// Seiko Epson S1C33 family -pub const EM_SE_C33: u16 = 107; -/// Sharp embedded microprocessor -pub const EM_SEP: u16 = 108; -/// Arca RISC -pub const EM_ARCA: u16 = 109; -/// PKU-Unity & MPRC Peking Uni. mc series -pub const EM_UNICORE: u16 = 110; -/// eXcess configurable cpu -pub const EM_EXCESS: u16 = 111; -/// Icera Semi. Deep Execution Processor -pub const EM_DXP: u16 = 112; -/// Altera Nios II -pub const EM_ALTERA_NIOS2: u16 = 113; -/// National Semi. CompactRISC CRX -pub const EM_CRX: u16 = 114; -/// Motorola XGATE -pub const EM_XGATE: u16 = 115; -/// Infineon C16x/XC16x -pub const EM_C166: u16 = 116; -/// Renesas M16C -pub const EM_M16C: u16 = 117; -/// Microchip Technology dsPIC30F -pub const EM_DSPIC30F: u16 = 118; -/// Freescale Communication Engine RISC -pub const EM_CE: u16 = 119; -/// Renesas M32C -pub const EM_M32C: u16 = 120; -/// Altium TSK3000 -pub const EM_TSK3000: u16 = 131; -/// Freescale RS08 -pub const EM_RS08: u16 = 132; -/// Analog Devices SHARC family -pub const EM_SHARC: u16 = 133; -/// Cyan Technology eCOG2 -pub const EM_ECOG2: u16 = 134; -/// Sunplus S+core7 RISC -pub const EM_SCORE7: u16 = 135; -/// New Japan Radio (NJR) 24-bit DSP -pub const EM_DSP24: u16 = 136; -/// Broadcom VideoCore III -pub const EM_VIDEOCORE3: u16 = 137; -/// RISC for Lattice FPGA -pub const EM_LATTICEMICO32: u16 = 138; -/// Seiko Epson C17 -pub const EM_SE_C17: u16 = 139; -/// Texas Instruments TMS320C6000 DSP -pub const EM_TI_C6000: u16 = 140; -/// Texas Instruments TMS320C2000 DSP -pub const EM_TI_C2000: u16 = 141; -/// Texas Instruments TMS320C55x DSP -pub const EM_TI_C5500: u16 = 142; -/// Texas Instruments App. Specific RISC -pub const EM_TI_ARP32: u16 = 143; -/// Texas Instruments Prog. Realtime Unit -pub const EM_TI_PRU: u16 = 144; -/// STMicroelectronics 64bit VLIW DSP -pub const EM_MMDSP_PLUS: u16 = 160; -/// Cypress M8C -pub const EM_CYPRESS_M8C: u16 = 161; -/// Renesas R32C -pub const EM_R32C: u16 = 162; -/// NXP Semi. TriMedia -pub const EM_TRIMEDIA: u16 = 163; -/// QUALCOMM Hexagon -pub const EM_HEXAGON: u16 = 164; -/// Intel 8051 and variants -pub const EM_8051: u16 = 165; -/// STMicroelectronics STxP7x -pub const EM_STXP7X: u16 = 166; -/// Andes Tech. compact code emb. RISC -pub const EM_NDS32: u16 = 167; -/// Cyan Technology eCOG1X -pub const EM_ECOG1X: u16 = 168; -/// Dallas Semi. MAXQ30 mc -pub const EM_MAXQ30: u16 = 169; -/// New Japan Radio (NJR) 16-bit DSP -pub const EM_XIMO16: u16 = 170; -/// M2000 Reconfigurable RISC -pub const EM_MANIK: u16 = 171; -/// Cray NV2 vector architecture -pub const EM_CRAYNV2: u16 = 172; -/// Renesas RX -pub const EM_RX: u16 = 173; -/// Imagination Tech. META -pub const EM_METAG: u16 = 174; -/// MCST Elbrus -pub const EM_MCST_ELBRUS: u16 = 175; -/// Cyan Technology eCOG16 -pub const EM_ECOG16: u16 = 176; -/// National Semi. CompactRISC CR16 -pub const EM_CR16: u16 = 177; -/// Freescale Extended Time Processing Unit -pub const EM_ETPU: u16 = 178; -/// Infineon Tech. SLE9X -pub const EM_SLE9X: u16 = 179; -/// Intel L10M -pub const EM_L10M: u16 = 180; -/// Intel K10M -pub const EM_K10M: u16 = 181; -/// ARM AARCH64 -pub const EM_AARCH64: u16 = 183; -/// Amtel 32-bit microprocessor -pub const EM_AVR32: u16 = 185; -/// STMicroelectronics STM8 -pub const EM_STM8: u16 = 186; -/// Tileta TILE64 -pub const EM_TILE64: u16 = 187; -/// Tilera TILEPro -pub const EM_TILEPRO: u16 = 188; -/// Xilinx MicroBlaze -pub const EM_MICROBLAZE: u16 = 189; -/// NVIDIA CUDA -pub const EM_CUDA: u16 = 190; -/// Tilera TILE-Gx -pub const EM_TILEGX: u16 = 191; -/// CloudShield -pub const EM_CLOUDSHIELD: u16 = 192; -/// KIPO-KAIST Core-A 1st gen. -pub const EM_COREA_1ST: u16 = 193; -/// KIPO-KAIST Core-A 2nd gen. -pub const EM_COREA_2ND: u16 = 194; -/// Synopsys ARCompact V2 -pub const EM_ARC_COMPACT2: u16 = 195; -/// Open8 RISC -pub const EM_OPEN8: u16 = 196; -/// Renesas RL78 -pub const EM_RL78: u16 = 197; -/// Broadcom VideoCore V -pub const EM_VIDEOCORE5: u16 = 198; -/// Renesas 78KOR -pub const EM_78KOR: u16 = 199; -/// Freescale 56800EX DSC -pub const EM_56800EX: u16 = 200; -/// Beyond BA1 -pub const EM_BA1: u16 = 201; -/// Beyond BA2 -pub const EM_BA2: u16 = 202; -/// XMOS xCORE -pub const EM_XCORE: u16 = 203; -/// Microchip 8-bit PIC(r) -pub const EM_MCHP_PIC: u16 = 204; -/// KM211 KM32 -pub const EM_KM32: u16 = 210; -/// KM211 KMX32 -pub const EM_KMX32: u16 = 211; -/// KM211 KMX16 -pub const EM_EMX16: u16 = 212; -/// KM211 KMX8 -pub const EM_EMX8: u16 = 213; -/// KM211 KVARC -pub const EM_KVARC: u16 = 214; -/// Paneve CDP -pub const EM_CDP: u16 = 215; -/// Cognitive Smart Memory Processor -pub const EM_COGE: u16 = 216; -/// Bluechip CoolEngine -pub const EM_COOL: u16 = 217; -/// Nanoradio Optimized RISC -pub const EM_NORC: u16 = 218; -/// CSR Kalimba -pub const EM_CSR_KALIMBA: u16 = 219; -/// Zilog Z80 -pub const EM_Z80: u16 = 220; -/// Controls and Data Services VISIUMcore -pub const EM_VISIUM: u16 = 221; -/// FTDI Chip FT32 -pub const EM_FT32: u16 = 222; -/// Moxie processor -pub const EM_MOXIE: u16 = 223; -/// AMD GPU -pub const EM_AMDGPU: u16 = 224; -/// RISC-V -pub const EM_RISCV: u16 = 243; -/// Linux BPF -- in-kernel virtual machine -pub const EM_BPF: u16 = 247; -/// C-SKY -pub const EM_CSKY: u16 = 252; -/// Loongson LoongArch -pub const EM_LOONGARCH: u16 = 258; -/// Solana Binary Format -pub const EM_SBF: u16 = 263; -/// Digital Alpha -pub const EM_ALPHA: u16 = 0x9026; - -// Values for `FileHeader*::e_version` and `Ident::version`. -/// Invalid ELF version. -pub const EV_NONE: u8 = 0; -/// Current ELF version. -pub const EV_CURRENT: u8 = 1; - -/// Section header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SectionHeader32 { - /// Section name. - /// - /// This is an offset into the section header string table. - pub sh_name: U32, - /// Section type. One of the `SHT_*` constants. - pub sh_type: U32, - /// Section flags. A combination of the `SHF_*` constants. - pub sh_flags: U32, - /// Section virtual address at execution. - pub sh_addr: U32, - /// Section file offset. - pub sh_offset: U32, - /// Section size in bytes. - pub sh_size: U32, - /// Link to another section. - /// - /// The section relationship depends on the `sh_type` value. - pub sh_link: U32, - /// Additional section information. - /// - /// The meaning of this field depends on the `sh_type` value. - pub sh_info: U32, - /// Section alignment. - pub sh_addralign: U32, - /// Entry size if the section holds a table. - pub sh_entsize: U32, -} - -/// Section header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SectionHeader64 { - /// Section name. - /// - /// This is an offset into the section header string table. - pub sh_name: U32, - /// Section type. One of the `SHT_*` constants. - pub sh_type: U32, - /// Section flags. A combination of the `SHF_*` constants. - pub sh_flags: U64, - /// Section virtual address at execution. - pub sh_addr: U64, - /// Section file offset. - pub sh_offset: U64, - /// Section size in bytes. - pub sh_size: U64, - /// Link to another section. - /// - /// The section relationship depends on the `sh_type` value. - pub sh_link: U32, - /// Additional section information. - /// - /// The meaning of this field depends on the `sh_type` value. - pub sh_info: U32, - /// Section alignment. - pub sh_addralign: U64, - /// Entry size if the section holds a table. - pub sh_entsize: U64, -} - -// Special values for section indices. -/// Undefined section. -pub const SHN_UNDEF: u16 = 0; -/// OS-specific range start. -/// Start of reserved section indices. -pub const SHN_LORESERVE: u16 = 0xff00; -/// Start of processor-specific section indices. -pub const SHN_LOPROC: u16 = 0xff00; -/// End of processor-specific section indices. -pub const SHN_HIPROC: u16 = 0xff1f; -/// Start of OS-specific section indices. -pub const SHN_LOOS: u16 = 0xff20; -/// End of OS-specific section indices. -pub const SHN_HIOS: u16 = 0xff3f; -/// Associated symbol is absolute. -pub const SHN_ABS: u16 = 0xfff1; -/// Associated symbol is common. -pub const SHN_COMMON: u16 = 0xfff2; -/// Section index is in the `SHT_SYMTAB_SHNDX` section. -pub const SHN_XINDEX: u16 = 0xffff; -/// End of reserved section indices. -pub const SHN_HIRESERVE: u16 = 0xffff; - -// Values for `SectionHeader*::sh_type`. -/// Section header table entry is unused. -pub const SHT_NULL: u32 = 0; -/// Program data. -pub const SHT_PROGBITS: u32 = 1; -/// Symbol table. -pub const SHT_SYMTAB: u32 = 2; -/// String table. -pub const SHT_STRTAB: u32 = 3; -/// Relocation entries with explicit addends. -pub const SHT_RELA: u32 = 4; -/// Symbol hash table. -pub const SHT_HASH: u32 = 5; -/// Dynamic linking information. -pub const SHT_DYNAMIC: u32 = 6; -/// Notes. -pub const SHT_NOTE: u32 = 7; -/// Program space with no data (bss). -pub const SHT_NOBITS: u32 = 8; -/// Relocation entries without explicit addends. -pub const SHT_REL: u32 = 9; -/// Reserved section type. -pub const SHT_SHLIB: u32 = 10; -/// Dynamic linker symbol table. -pub const SHT_DYNSYM: u32 = 11; -/// Array of constructors. -pub const SHT_INIT_ARRAY: u32 = 14; -/// Array of destructors. -pub const SHT_FINI_ARRAY: u32 = 15; -/// Array of pre-constructors. -pub const SHT_PREINIT_ARRAY: u32 = 16; -/// Section group. -pub const SHT_GROUP: u32 = 17; -/// Extended section indices for a symbol table. -pub const SHT_SYMTAB_SHNDX: u32 = 18; -/// Start of OS-specific section types. -pub const SHT_LOOS: u32 = 0x6000_0000; -/// Object attributes. -pub const SHT_GNU_ATTRIBUTES: u32 = 0x6fff_fff5; -/// GNU-style hash table. -pub const SHT_GNU_HASH: u32 = 0x6fff_fff6; -/// Prelink library list -pub const SHT_GNU_LIBLIST: u32 = 0x6fff_fff7; -/// Checksum for DSO content. -pub const SHT_CHECKSUM: u32 = 0x6fff_fff8; -/// Sun-specific low bound. -pub const SHT_LOSUNW: u32 = 0x6fff_fffa; -#[allow(non_upper_case_globals)] -pub const SHT_SUNW_move: u32 = 0x6fff_fffa; -pub const SHT_SUNW_COMDAT: u32 = 0x6fff_fffb; -#[allow(non_upper_case_globals)] -pub const SHT_SUNW_syminfo: u32 = 0x6fff_fffc; -/// Version definition section. -#[allow(non_upper_case_globals)] -pub const SHT_GNU_VERDEF: u32 = 0x6fff_fffd; -/// Version needs section. -#[allow(non_upper_case_globals)] -pub const SHT_GNU_VERNEED: u32 = 0x6fff_fffe; -/// Version symbol table. -#[allow(non_upper_case_globals)] -pub const SHT_GNU_VERSYM: u32 = 0x6fff_ffff; -/// Sun-specific high bound. -pub const SHT_HISUNW: u32 = 0x6fff_ffff; -/// End of OS-specific section types. -pub const SHT_HIOS: u32 = 0x6fff_ffff; -/// Start of processor-specific section types. -pub const SHT_LOPROC: u32 = 0x7000_0000; -/// End of processor-specific section types. -pub const SHT_HIPROC: u32 = 0x7fff_ffff; -/// Start of application-specific section types. -pub const SHT_LOUSER: u32 = 0x8000_0000; -/// End of application-specific section types. -pub const SHT_HIUSER: u32 = 0x8fff_ffff; - -// Values for `SectionHeader*::sh_flags`. -/// Section is writable. -pub const SHF_WRITE: u32 = 1 << 0; -/// Section occupies memory during execution. -pub const SHF_ALLOC: u32 = 1 << 1; -/// Section is executable. -pub const SHF_EXECINSTR: u32 = 1 << 2; -/// Section may be be merged to eliminate duplication. -pub const SHF_MERGE: u32 = 1 << 4; -/// Section contains nul-terminated strings. -pub const SHF_STRINGS: u32 = 1 << 5; -/// The `sh_info` field contains a section header table index. -pub const SHF_INFO_LINK: u32 = 1 << 6; -/// Section has special ordering requirements when combining sections. -pub const SHF_LINK_ORDER: u32 = 1 << 7; -/// Section requires special OS-specific handling. -pub const SHF_OS_NONCONFORMING: u32 = 1 << 8; -/// Section is a member of a group. -pub const SHF_GROUP: u32 = 1 << 9; -/// Section holds thread-local storage. -pub const SHF_TLS: u32 = 1 << 10; -/// Section is compressed. -/// -/// Compressed sections begin with one of the `CompressionHeader*` headers. -pub const SHF_COMPRESSED: u32 = 1 << 11; -/// OS-specific section flags. -pub const SHF_MASKOS: u32 = 0x0ff0_0000; -/// Processor-specific section flags. -pub const SHF_MASKPROC: u32 = 0xf000_0000; -/// This section is excluded from the final executable or shared library. -pub const SHF_EXCLUDE: u32 = 0x8000_0000; - -/// Section compression header. -/// -/// Used when `SHF_COMPRESSED` is set. -/// -/// Note: this type currently allows for misaligned headers, but that may be -/// changed in a future version. -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct CompressionHeader32 { - /// Compression format. One of the `ELFCOMPRESS_*` values. - pub ch_type: U32Bytes, - /// Uncompressed data size. - pub ch_size: U32Bytes, - /// Uncompressed data alignment. - pub ch_addralign: U32Bytes, -} - -/// Section compression header. -/// -/// Used when `SHF_COMPRESSED` is set. -/// -/// Note: this type currently allows for misaligned headers, but that may be -/// changed in a future version. -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct CompressionHeader64 { - /// Compression format. One of the `ELFCOMPRESS_*` values. - pub ch_type: U32Bytes, - /// Reserved. - pub ch_reserved: U32Bytes, - /// Uncompressed data size. - pub ch_size: U64Bytes, - /// Uncompressed data alignment. - pub ch_addralign: U64Bytes, -} - -/// ZLIB/DEFLATE algorithm. -pub const ELFCOMPRESS_ZLIB: u32 = 1; -/// Zstandard algorithm. -pub const ELFCOMPRESS_ZSTD: u32 = 2; -/// Start of OS-specific compression types. -pub const ELFCOMPRESS_LOOS: u32 = 0x6000_0000; -/// End of OS-specific compression types. -pub const ELFCOMPRESS_HIOS: u32 = 0x6fff_ffff; -/// Start of processor-specific compression types. -pub const ELFCOMPRESS_LOPROC: u32 = 0x7000_0000; -/// End of processor-specific compression types. -pub const ELFCOMPRESS_HIPROC: u32 = 0x7fff_ffff; - -// Values for the flag entry for section groups. -/// Mark group as COMDAT. -pub const GRP_COMDAT: u32 = 1; - -/// Symbol table entry. -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct Sym32 { - /// Symbol name. - /// - /// This is an offset into the symbol string table. - pub st_name: U32, - /// Symbol value. - pub st_value: U32, - /// Symbol size. - pub st_size: U32, - /// Symbol type and binding. - /// - /// Use the `st_type` and `st_bind` methods to access this value. - pub st_info: u8, - /// Symbol visibility. - /// - /// Use the `st_visibility` method to access this value. - pub st_other: u8, - /// Section index or one of the `SHN_*` values. - pub st_shndx: U16, -} - -impl Sym32 { - /// Get the `st_bind` component of the `st_info` field. - #[inline] - pub fn st_bind(&self) -> u8 { - self.st_info >> 4 - } - - /// Get the `st_type` component of the `st_info` field. - #[inline] - pub fn st_type(&self) -> u8 { - self.st_info & 0xf - } - - /// Set the `st_info` field given the `st_bind` and `st_type` components. - #[inline] - pub fn set_st_info(&mut self, st_bind: u8, st_type: u8) { - self.st_info = (st_bind << 4) + (st_type & 0xf); - } - - /// Get the `st_visibility` component of the `st_info` field. - #[inline] - pub fn st_visibility(&self) -> u8 { - self.st_other & 0x3 - } -} - -/// Symbol table entry. -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct Sym64 { - /// Symbol name. - /// - /// This is an offset into the symbol string table. - pub st_name: U32, - /// Symbol type and binding. - /// - /// Use the `st_bind` and `st_type` methods to access this value. - pub st_info: u8, - /// Symbol visibility. - /// - /// Use the `st_visibility` method to access this value. - pub st_other: u8, - /// Section index or one of the `SHN_*` values. - pub st_shndx: U16, - /// Symbol value. - pub st_value: U64, - /// Symbol size. - pub st_size: U64, -} - -impl Sym64 { - /// Get the `st_bind` component of the `st_info` field. - #[inline] - pub fn st_bind(&self) -> u8 { - self.st_info >> 4 - } - - /// Get the `st_type` component of the `st_info` field. - #[inline] - pub fn st_type(&self) -> u8 { - self.st_info & 0xf - } - - /// Set the `st_info` field given the `st_bind` and `st_type` components. - #[inline] - pub fn set_st_info(&mut self, st_bind: u8, st_type: u8) { - self.st_info = (st_bind << 4) + (st_type & 0xf); - } - - /// Get the `st_visibility` component of the `st_info` field. - #[inline] - pub fn st_visibility(&self) -> u8 { - self.st_other & 0x3 - } -} - -/// Additional information about a `Sym32`. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Syminfo32 { - /// Direct bindings, symbol bound to. - pub si_boundto: U16, - /// Per symbol flags. - pub si_flags: U16, -} - -/// Additional information about a `Sym64`. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Syminfo64 { - /// Direct bindings, symbol bound to. - pub si_boundto: U16, - /// Per symbol flags. - pub si_flags: U16, -} - -// Values for `Syminfo*::si_boundto`. -/// Symbol bound to self -pub const SYMINFO_BT_SELF: u16 = 0xffff; -/// Symbol bound to parent -pub const SYMINFO_BT_PARENT: u16 = 0xfffe; -/// Beginning of reserved entries -pub const SYMINFO_BT_LOWRESERVE: u16 = 0xff00; - -// Values for `Syminfo*::si_flags`. -/// Direct bound symbol -pub const SYMINFO_FLG_DIRECT: u16 = 0x0001; -/// Pass-thru symbol for translator -pub const SYMINFO_FLG_PASSTHRU: u16 = 0x0002; -/// Symbol is a copy-reloc -pub const SYMINFO_FLG_COPY: u16 = 0x0004; -/// Symbol bound to object to be lazy loaded -pub const SYMINFO_FLG_LAZYLOAD: u16 = 0x0008; - -// Syminfo version values. -pub const SYMINFO_NONE: u16 = 0; -pub const SYMINFO_CURRENT: u16 = 1; -pub const SYMINFO_NUM: u16 = 2; - -// Values for bind component of `Sym*::st_info`. -/// Local symbol. -pub const STB_LOCAL: u8 = 0; -/// Global symbol. -pub const STB_GLOBAL: u8 = 1; -/// Weak symbol. -pub const STB_WEAK: u8 = 2; -/// Start of OS-specific symbol binding. -pub const STB_LOOS: u8 = 10; -/// Unique symbol. -pub const STB_GNU_UNIQUE: u8 = 10; -/// End of OS-specific symbol binding. -pub const STB_HIOS: u8 = 12; -/// Start of processor-specific symbol binding. -pub const STB_LOPROC: u8 = 13; -/// End of processor-specific symbol binding. -pub const STB_HIPROC: u8 = 15; - -// Values for type component of `Sym*::st_info`. -/// Symbol type is unspecified. -pub const STT_NOTYPE: u8 = 0; -/// Symbol is a data object. -pub const STT_OBJECT: u8 = 1; -/// Symbol is a code object. -pub const STT_FUNC: u8 = 2; -/// Symbol is associated with a section. -pub const STT_SECTION: u8 = 3; -/// Symbol's name is a file name. -pub const STT_FILE: u8 = 4; -/// Symbol is a common data object. -pub const STT_COMMON: u8 = 5; -/// Symbol is a thread-local storage object. -pub const STT_TLS: u8 = 6; -/// Start of OS-specific symbol types. -pub const STT_LOOS: u8 = 10; -/// Symbol is an indirect code object. -pub const STT_GNU_IFUNC: u8 = 10; -/// End of OS-specific symbol types. -pub const STT_HIOS: u8 = 12; -/// Start of processor-specific symbol types. -pub const STT_LOPROC: u8 = 13; -/// End of processor-specific symbol types. -pub const STT_HIPROC: u8 = 15; - -// Values for visibility component of `Symbol*::st_other`. -/// Default symbol visibility rules. -pub const STV_DEFAULT: u8 = 0; -/// Processor specific hidden class. -pub const STV_INTERNAL: u8 = 1; -/// Symbol is not visible to other components. -pub const STV_HIDDEN: u8 = 2; -/// Symbol is visible to other components, but is not preemptible. -pub const STV_PROTECTED: u8 = 3; - -/// Relocation table entry without explicit addend. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rel32 { - /// Relocation address. - pub r_offset: U32, - /// Relocation type and symbol index. - pub r_info: U32, -} - -impl Rel32 { - /// Get the `r_sym` component of the `r_info` field. - #[inline] - pub fn r_sym(&self, endian: E) -> u32 { - self.r_info.get(endian) >> 8 - } - - /// Get the `r_type` component of the `r_info` field. - #[inline] - pub fn r_type(&self, endian: E) -> u32 { - self.r_info.get(endian) & 0xff - } - - /// Calculate the `r_info` field given the `r_sym` and `r_type` components. - pub fn r_info(endian: E, r_sym: u32, r_type: u8) -> U32 { - U32::new(endian, (r_sym << 8) | u32::from(r_type)) - } - - /// Set the `r_info` field given the `r_sym` and `r_type` components. - pub fn set_r_info(&mut self, endian: E, r_sym: u32, r_type: u8) { - self.r_info = Self::r_info(endian, r_sym, r_type) - } -} - -/// Relocation table entry with explicit addend. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rela32 { - /// Relocation address. - pub r_offset: U32, - /// Relocation type and symbol index. - pub r_info: U32, - /// Explicit addend. - pub r_addend: I32, -} - -impl Rela32 { - /// Get the `r_sym` component of the `r_info` field. - #[inline] - pub fn r_sym(&self, endian: E) -> u32 { - self.r_info.get(endian) >> 8 - } - - /// Get the `r_type` component of the `r_info` field. - #[inline] - pub fn r_type(&self, endian: E) -> u32 { - self.r_info.get(endian) & 0xff - } - - /// Calculate the `r_info` field given the `r_sym` and `r_type` components. - pub fn r_info(endian: E, r_sym: u32, r_type: u8) -> U32 { - U32::new(endian, (r_sym << 8) | u32::from(r_type)) - } - - /// Set the `r_info` field given the `r_sym` and `r_type` components. - pub fn set_r_info(&mut self, endian: E, r_sym: u32, r_type: u8) { - self.r_info = Self::r_info(endian, r_sym, r_type) - } -} - -impl From> for Rela32 { - fn from(rel: Rel32) -> Self { - Rela32 { - r_offset: rel.r_offset, - r_info: rel.r_info, - r_addend: I32::default(), - } - } -} - -/// Relocation table entry without explicit addend. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rel64 { - /// Relocation address. - pub r_offset: U64, - /// Relocation type and symbol index. - pub r_info: U64, -} - -impl Rel64 { - /// Get the `r_sym` component of the `r_info` field. - #[inline] - pub fn r_sym(&self, endian: E) -> u32 { - (self.r_info.get(endian) >> 32) as u32 - } - - /// Get the `r_type` component of the `r_info` field. - #[inline] - pub fn r_type(&self, endian: E) -> u32 { - (self.r_info.get(endian) & 0xffff_ffff) as u32 - } - - /// Calculate the `r_info` field given the `r_sym` and `r_type` components. - pub fn r_info(endian: E, r_sym: u32, r_type: u32) -> U64 { - U64::new(endian, (u64::from(r_sym) << 32) | u64::from(r_type)) - } - - /// Set the `r_info` field given the `r_sym` and `r_type` components. - pub fn set_r_info(&mut self, endian: E, r_sym: u32, r_type: u32) { - self.r_info = Self::r_info(endian, r_sym, r_type) - } -} - -impl From> for Rela64 { - fn from(rel: Rel64) -> Self { - Rela64 { - r_offset: rel.r_offset, - r_info: rel.r_info, - r_addend: I64::default(), - } - } -} - -/// Relocation table entry with explicit addend. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rela64 { - /// Relocation address. - pub r_offset: U64, - /// Relocation type and symbol index. - pub r_info: U64, - /// Explicit addend. - pub r_addend: I64, -} - -impl Rela64 { - pub(crate) fn get_r_info(&self, endian: E, is_mips64el: bool) -> u64 { - let mut t = self.r_info.get(endian); - if is_mips64el { - t = (t << 32) - | ((t >> 8) & 0xff000000) - | ((t >> 24) & 0x00ff0000) - | ((t >> 40) & 0x0000ff00) - | ((t >> 56) & 0x000000ff); - } - t - } - - /// Get the `r_sym` component of the `r_info` field. - #[inline] - pub fn r_sym(&self, endian: E, is_mips64el: bool) -> u32 { - (self.get_r_info(endian, is_mips64el) >> 32) as u32 - } - - /// Get the `r_type` component of the `r_info` field. - #[inline] - pub fn r_type(&self, endian: E, is_mips64el: bool) -> u32 { - (self.get_r_info(endian, is_mips64el) & 0xffff_ffff) as u32 - } - - /// Calculate the `r_info` field given the `r_sym` and `r_type` components. - pub fn r_info(endian: E, is_mips64el: bool, r_sym: u32, r_type: u32) -> U64 { - let mut t = (u64::from(r_sym) << 32) | u64::from(r_type); - if is_mips64el { - t = (t >> 32) - | ((t & 0xff000000) << 8) - | ((t & 0x00ff0000) << 24) - | ((t & 0x0000ff00) << 40) - | ((t & 0x000000ff) << 56); - } - U64::new(endian, t) - } - - /// Set the `r_info` field given the `r_sym` and `r_type` components. - pub fn set_r_info(&mut self, endian: E, is_mips64el: bool, r_sym: u32, r_type: u32) { - self.r_info = Self::r_info(endian, is_mips64el, r_sym, r_type); - } -} - -/// Program segment header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ProgramHeader32 { - /// Segment type. One of the `PT_*` constants. - pub p_type: U32, - /// Segment file offset. - pub p_offset: U32, - /// Segment virtual address. - pub p_vaddr: U32, - /// Segment physical address. - pub p_paddr: U32, - /// Segment size in the file. - pub p_filesz: U32, - /// Segment size in memory. - pub p_memsz: U32, - /// Segment flags. A combination of the `PF_*` constants. - pub p_flags: U32, - /// Segment alignment. - pub p_align: U32, -} - -/// Program segment header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ProgramHeader64 { - /// Segment type. One of the `PT_*` constants. - pub p_type: U32, - /// Segment flags. A combination of the `PF_*` constants. - pub p_flags: U32, - /// Segment file offset. - pub p_offset: U64, - /// Segment virtual address. - pub p_vaddr: U64, - /// Segment physical address. - pub p_paddr: U64, - /// Segment size in the file. - pub p_filesz: U64, - /// Segment size in memory. - pub p_memsz: U64, - /// Segment alignment. - pub p_align: U64, -} - -/// Special value for `FileHeader*::e_phnum`. -/// -/// This indicates that the real number of program headers is too large to fit into e_phnum. -/// Instead the real value is in the field `sh_info` of section 0. -pub const PN_XNUM: u16 = 0xffff; - -// Values for `ProgramHeader*::p_type`. -/// Program header table entry is unused. -pub const PT_NULL: u32 = 0; -/// Loadable program segment. -pub const PT_LOAD: u32 = 1; -/// Dynamic linking information. -pub const PT_DYNAMIC: u32 = 2; -/// Program interpreter. -pub const PT_INTERP: u32 = 3; -/// Auxiliary information. -pub const PT_NOTE: u32 = 4; -/// Reserved. -pub const PT_SHLIB: u32 = 5; -/// Segment contains the program header table. -pub const PT_PHDR: u32 = 6; -/// Thread-local storage segment. -pub const PT_TLS: u32 = 7; -/// Start of OS-specific segment types. -pub const PT_LOOS: u32 = 0x6000_0000; -/// GCC `.eh_frame_hdr` segment. -pub const PT_GNU_EH_FRAME: u32 = 0x6474_e550; -/// Indicates stack executability. -pub const PT_GNU_STACK: u32 = 0x6474_e551; -/// Read-only after relocation. -pub const PT_GNU_RELRO: u32 = 0x6474_e552; -/// Segment containing `.note.gnu.property` section. -pub const PT_GNU_PROPERTY: u32 = 0x6474_e553; -/// End of OS-specific segment types. -pub const PT_HIOS: u32 = 0x6fff_ffff; -/// Start of processor-specific segment types. -pub const PT_LOPROC: u32 = 0x7000_0000; -/// End of processor-specific segment types. -pub const PT_HIPROC: u32 = 0x7fff_ffff; - -// Values for `ProgramHeader*::p_flags`. -/// Segment is executable. -pub const PF_X: u32 = 1 << 0; -/// Segment is writable. -pub const PF_W: u32 = 1 << 1; -/// Segment is readable. -pub const PF_R: u32 = 1 << 2; -/// OS-specific segment flags. -pub const PF_MASKOS: u32 = 0x0ff0_0000; -/// Processor-specific segment flags. -pub const PF_MASKPROC: u32 = 0xf000_0000; - -/// Note name for core files. -pub const ELF_NOTE_CORE: &[u8] = b"CORE"; -/// Note name for linux core files. -/// -/// Notes in linux core files may also use `ELF_NOTE_CORE`. -pub const ELF_NOTE_LINUX: &[u8] = b"LINUX"; - -// Values for `NoteHeader*::n_type` in core files. -// -/// Contains copy of prstatus struct. -pub const NT_PRSTATUS: u32 = 1; -/// Contains copy of fpregset struct. -pub const NT_PRFPREG: u32 = 2; -/// Contains copy of fpregset struct. -pub const NT_FPREGSET: u32 = 2; -/// Contains copy of prpsinfo struct. -pub const NT_PRPSINFO: u32 = 3; -/// Contains copy of prxregset struct. -pub const NT_PRXREG: u32 = 4; -/// Contains copy of task structure. -pub const NT_TASKSTRUCT: u32 = 4; -/// String from sysinfo(SI_PLATFORM). -pub const NT_PLATFORM: u32 = 5; -/// Contains copy of auxv array. -pub const NT_AUXV: u32 = 6; -/// Contains copy of gwindows struct. -pub const NT_GWINDOWS: u32 = 7; -/// Contains copy of asrset struct. -pub const NT_ASRS: u32 = 8; -/// Contains copy of pstatus struct. -pub const NT_PSTATUS: u32 = 10; -/// Contains copy of psinfo struct. -pub const NT_PSINFO: u32 = 13; -/// Contains copy of prcred struct. -pub const NT_PRCRED: u32 = 14; -/// Contains copy of utsname struct. -pub const NT_UTSNAME: u32 = 15; -/// Contains copy of lwpstatus struct. -pub const NT_LWPSTATUS: u32 = 16; -/// Contains copy of lwpinfo struct. -pub const NT_LWPSINFO: u32 = 17; -/// Contains copy of fprxregset struct. -pub const NT_PRFPXREG: u32 = 20; -/// Contains copy of siginfo_t, size might increase. -pub const NT_SIGINFO: u32 = 0x5349_4749; -/// Contains information about mapped files. -pub const NT_FILE: u32 = 0x4649_4c45; -/// Contains copy of user_fxsr_struct. -pub const NT_PRXFPREG: u32 = 0x46e6_2b7f; -/// PowerPC Altivec/VMX registers. -pub const NT_PPC_VMX: u32 = 0x100; -/// PowerPC SPE/EVR registers. -pub const NT_PPC_SPE: u32 = 0x101; -/// PowerPC VSX registers. -pub const NT_PPC_VSX: u32 = 0x102; -/// Target Address Register. -pub const NT_PPC_TAR: u32 = 0x103; -/// Program Priority Register. -pub const NT_PPC_PPR: u32 = 0x104; -/// Data Stream Control Register. -pub const NT_PPC_DSCR: u32 = 0x105; -/// Event Based Branch Registers. -pub const NT_PPC_EBB: u32 = 0x106; -/// Performance Monitor Registers. -pub const NT_PPC_PMU: u32 = 0x107; -/// TM checkpointed GPR Registers. -pub const NT_PPC_TM_CGPR: u32 = 0x108; -/// TM checkpointed FPR Registers. -pub const NT_PPC_TM_CFPR: u32 = 0x109; -/// TM checkpointed VMX Registers. -pub const NT_PPC_TM_CVMX: u32 = 0x10a; -/// TM checkpointed VSX Registers. -pub const NT_PPC_TM_CVSX: u32 = 0x10b; -/// TM Special Purpose Registers. -pub const NT_PPC_TM_SPR: u32 = 0x10c; -/// TM checkpointed Target Address Register. -pub const NT_PPC_TM_CTAR: u32 = 0x10d; -/// TM checkpointed Program Priority Register. -pub const NT_PPC_TM_CPPR: u32 = 0x10e; -/// TM checkpointed Data Stream Control Register. -pub const NT_PPC_TM_CDSCR: u32 = 0x10f; -/// Memory Protection Keys registers. -pub const NT_PPC_PKEY: u32 = 0x110; -/// i386 TLS slots (struct user_desc). -pub const NT_386_TLS: u32 = 0x200; -/// x86 io permission bitmap (1=deny). -pub const NT_386_IOPERM: u32 = 0x201; -/// x86 extended state using xsave. -pub const NT_X86_XSTATE: u32 = 0x202; -/// s390 upper register halves. -pub const NT_S390_HIGH_GPRS: u32 = 0x300; -/// s390 timer register. -pub const NT_S390_TIMER: u32 = 0x301; -/// s390 TOD clock comparator register. -pub const NT_S390_TODCMP: u32 = 0x302; -/// s390 TOD programmable register. -pub const NT_S390_TODPREG: u32 = 0x303; -/// s390 control registers. -pub const NT_S390_CTRS: u32 = 0x304; -/// s390 prefix register. -pub const NT_S390_PREFIX: u32 = 0x305; -/// s390 breaking event address. -pub const NT_S390_LAST_BREAK: u32 = 0x306; -/// s390 system call restart data. -pub const NT_S390_SYSTEM_CALL: u32 = 0x307; -/// s390 transaction diagnostic block. -pub const NT_S390_TDB: u32 = 0x308; -/// s390 vector registers 0-15 upper half. -pub const NT_S390_VXRS_LOW: u32 = 0x309; -/// s390 vector registers 16-31. -pub const NT_S390_VXRS_HIGH: u32 = 0x30a; -/// s390 guarded storage registers. -pub const NT_S390_GS_CB: u32 = 0x30b; -/// s390 guarded storage broadcast control block. -pub const NT_S390_GS_BC: u32 = 0x30c; -/// s390 runtime instrumentation. -pub const NT_S390_RI_CB: u32 = 0x30d; -/// ARM VFP/NEON registers. -pub const NT_ARM_VFP: u32 = 0x400; -/// ARM TLS register. -pub const NT_ARM_TLS: u32 = 0x401; -/// ARM hardware breakpoint registers. -pub const NT_ARM_HW_BREAK: u32 = 0x402; -/// ARM hardware watchpoint registers. -pub const NT_ARM_HW_WATCH: u32 = 0x403; -/// ARM system call number. -pub const NT_ARM_SYSTEM_CALL: u32 = 0x404; -/// ARM Scalable Vector Extension registers. -pub const NT_ARM_SVE: u32 = 0x405; -/// Vmcore Device Dump Note. -pub const NT_VMCOREDD: u32 = 0x700; -/// MIPS DSP ASE registers. -pub const NT_MIPS_DSP: u32 = 0x800; -/// MIPS floating-point mode. -pub const NT_MIPS_FP_MODE: u32 = 0x801; - -/// Note type for version string. -/// -/// This note may appear in object files. -/// -/// It must be handled as a special case because it has no descriptor, and instead -/// uses the note name as the version string. -pub const NT_VERSION: u32 = 1; - -/// Dynamic section entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Dyn32 { - /// Dynamic entry type. - pub d_tag: U32, - /// Value (integer or address). - pub d_val: U32, -} - -/// Dynamic section entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Dyn64 { - /// Dynamic entry type. - pub d_tag: U64, - /// Value (integer or address). - pub d_val: U64, -} - -// Values for `Dyn*::d_tag`. - -/// Marks end of dynamic section -pub const DT_NULL: u32 = 0; -/// Name of needed library -pub const DT_NEEDED: u32 = 1; -/// Size in bytes of PLT relocs -pub const DT_PLTRELSZ: u32 = 2; -/// Processor defined value -pub const DT_PLTGOT: u32 = 3; -/// Address of symbol hash table -pub const DT_HASH: u32 = 4; -/// Address of string table -pub const DT_STRTAB: u32 = 5; -/// Address of symbol table -pub const DT_SYMTAB: u32 = 6; -/// Address of Rela relocs -pub const DT_RELA: u32 = 7; -/// Total size of Rela relocs -pub const DT_RELASZ: u32 = 8; -/// Size of one Rela reloc -pub const DT_RELAENT: u32 = 9; -/// Size of string table -pub const DT_STRSZ: u32 = 10; -/// Size of one symbol table entry -pub const DT_SYMENT: u32 = 11; -/// Address of init function -pub const DT_INIT: u32 = 12; -/// Address of termination function -pub const DT_FINI: u32 = 13; -/// Name of shared object -pub const DT_SONAME: u32 = 14; -/// Library search path (deprecated) -pub const DT_RPATH: u32 = 15; -/// Start symbol search here -pub const DT_SYMBOLIC: u32 = 16; -/// Address of Rel relocs -pub const DT_REL: u32 = 17; -/// Total size of Rel relocs -pub const DT_RELSZ: u32 = 18; -/// Size of one Rel reloc -pub const DT_RELENT: u32 = 19; -/// Type of reloc in PLT -pub const DT_PLTREL: u32 = 20; -/// For debugging; unspecified -pub const DT_DEBUG: u32 = 21; -/// Reloc might modify .text -pub const DT_TEXTREL: u32 = 22; -/// Address of PLT relocs -pub const DT_JMPREL: u32 = 23; -/// Process relocations of object -pub const DT_BIND_NOW: u32 = 24; -/// Array with addresses of init fct -pub const DT_INIT_ARRAY: u32 = 25; -/// Array with addresses of fini fct -pub const DT_FINI_ARRAY: u32 = 26; -/// Size in bytes of DT_INIT_ARRAY -pub const DT_INIT_ARRAYSZ: u32 = 27; -/// Size in bytes of DT_FINI_ARRAY -pub const DT_FINI_ARRAYSZ: u32 = 28; -/// Library search path -pub const DT_RUNPATH: u32 = 29; -/// Flags for the object being loaded -pub const DT_FLAGS: u32 = 30; -/// Start of encoded range -pub const DT_ENCODING: u32 = 32; -/// Array with addresses of preinit fct -pub const DT_PREINIT_ARRAY: u32 = 32; -/// size in bytes of DT_PREINIT_ARRAY -pub const DT_PREINIT_ARRAYSZ: u32 = 33; -/// Address of SYMTAB_SHNDX section -pub const DT_SYMTAB_SHNDX: u32 = 34; -/// Start of OS-specific -pub const DT_LOOS: u32 = 0x6000_000d; -/// End of OS-specific -pub const DT_HIOS: u32 = 0x6fff_f000; -/// Start of processor-specific -pub const DT_LOPROC: u32 = 0x7000_0000; -/// End of processor-specific -pub const DT_HIPROC: u32 = 0x7fff_ffff; - -// `DT_*` entries between `DT_VALRNGHI` & `DT_VALRNGLO` use `d_val` as a value. -pub const DT_VALRNGLO: u32 = 0x6fff_fd00; -/// Prelinking timestamp -pub const DT_GNU_PRELINKED: u32 = 0x6fff_fdf5; -/// Size of conflict section -pub const DT_GNU_CONFLICTSZ: u32 = 0x6fff_fdf6; -/// Size of library list -pub const DT_GNU_LIBLISTSZ: u32 = 0x6fff_fdf7; -pub const DT_CHECKSUM: u32 = 0x6fff_fdf8; -pub const DT_PLTPADSZ: u32 = 0x6fff_fdf9; -pub const DT_MOVEENT: u32 = 0x6fff_fdfa; -pub const DT_MOVESZ: u32 = 0x6fff_fdfb; -/// Feature selection (DTF_*). -pub const DT_FEATURE_1: u32 = 0x6fff_fdfc; -/// Flags for DT_* entries, affecting the following DT_* entry. -pub const DT_POSFLAG_1: u32 = 0x6fff_fdfd; -/// Size of syminfo table (in bytes) -pub const DT_SYMINSZ: u32 = 0x6fff_fdfe; -/// Entry size of syminfo -pub const DT_SYMINENT: u32 = 0x6fff_fdff; -pub const DT_VALRNGHI: u32 = 0x6fff_fdff; - -// `DT_*` entries between `DT_ADDRRNGHI` & `DT_ADDRRNGLO` use `d_val` as an address. -// -// If any adjustment is made to the ELF object after it has been -// built these entries will need to be adjusted. -pub const DT_ADDRRNGLO: u32 = 0x6fff_fe00; -/// GNU-style hash table. -pub const DT_GNU_HASH: u32 = 0x6fff_fef5; -pub const DT_TLSDESC_PLT: u32 = 0x6fff_fef6; -pub const DT_TLSDESC_GOT: u32 = 0x6fff_fef7; -/// Start of conflict section -pub const DT_GNU_CONFLICT: u32 = 0x6fff_fef8; -/// Library list -pub const DT_GNU_LIBLIST: u32 = 0x6fff_fef9; -/// Configuration information. -pub const DT_CONFIG: u32 = 0x6fff_fefa; -/// Dependency auditing. -pub const DT_DEPAUDIT: u32 = 0x6fff_fefb; -/// Object auditing. -pub const DT_AUDIT: u32 = 0x6fff_fefc; -/// PLT padding. -pub const DT_PLTPAD: u32 = 0x6fff_fefd; -/// Move table. -pub const DT_MOVETAB: u32 = 0x6fff_fefe; -/// Syminfo table. -pub const DT_SYMINFO: u32 = 0x6fff_feff; -pub const DT_ADDRRNGHI: u32 = 0x6fff_feff; - -// The versioning entry types. The next are defined as part of the -// GNU extension. -pub const DT_VERSYM: u32 = 0x6fff_fff0; -pub const DT_RELACOUNT: u32 = 0x6fff_fff9; -pub const DT_RELCOUNT: u32 = 0x6fff_fffa; -/// State flags, see DF_1_* below. -pub const DT_FLAGS_1: u32 = 0x6fff_fffb; -/// Address of version definition table -pub const DT_VERDEF: u32 = 0x6fff_fffc; -/// Number of version definitions -pub const DT_VERDEFNUM: u32 = 0x6fff_fffd; -/// Address of table with needed versions -pub const DT_VERNEED: u32 = 0x6fff_fffe; -/// Number of needed versions -pub const DT_VERNEEDNUM: u32 = 0x6fff_ffff; - -// Machine-independent extensions in the "processor-specific" range. -/// Shared object to load before self -pub const DT_AUXILIARY: u32 = 0x7fff_fffd; -/// Shared object to get values from -pub const DT_FILTER: u32 = 0x7fff_ffff; - -// Values of `Dyn*::d_val` in the `DT_FLAGS` entry. -/// Object may use DF_ORIGIN -pub const DF_ORIGIN: u32 = 0x0000_0001; -/// Symbol resolutions starts here -pub const DF_SYMBOLIC: u32 = 0x0000_0002; -/// Object contains text relocations -pub const DF_TEXTREL: u32 = 0x0000_0004; -/// No lazy binding for this object -pub const DF_BIND_NOW: u32 = 0x0000_0008; -/// Module uses the static TLS model -pub const DF_STATIC_TLS: u32 = 0x0000_0010; - -// Values of `Dyn*::d_val` in the `DT_FLAGS_1` entry. -/// Set RTLD_NOW for this object. -pub const DF_1_NOW: u32 = 0x0000_0001; -/// Set RTLD_GLOBAL for this object. -pub const DF_1_GLOBAL: u32 = 0x0000_0002; -/// Set RTLD_GROUP for this object. -pub const DF_1_GROUP: u32 = 0x0000_0004; -/// Set RTLD_NODELETE for this object. -pub const DF_1_NODELETE: u32 = 0x0000_0008; -/// Trigger filtee loading at runtime. -pub const DF_1_LOADFLTR: u32 = 0x0000_0010; -/// Set RTLD_INITFIRST for this object. -pub const DF_1_INITFIRST: u32 = 0x0000_0020; -/// Set RTLD_NOOPEN for this object. -pub const DF_1_NOOPEN: u32 = 0x0000_0040; -/// $ORIGIN must be handled. -pub const DF_1_ORIGIN: u32 = 0x0000_0080; -/// Direct binding enabled. -pub const DF_1_DIRECT: u32 = 0x0000_0100; -pub const DF_1_TRANS: u32 = 0x0000_0200; -/// Object is used to interpose. -pub const DF_1_INTERPOSE: u32 = 0x0000_0400; -/// Ignore default lib search path. -pub const DF_1_NODEFLIB: u32 = 0x0000_0800; -/// Object can't be dldump'ed. -pub const DF_1_NODUMP: u32 = 0x0000_1000; -/// Configuration alternative created. -pub const DF_1_CONFALT: u32 = 0x0000_2000; -/// Filtee terminates filters search. -pub const DF_1_ENDFILTEE: u32 = 0x0000_4000; -/// Disp reloc applied at build time. -pub const DF_1_DISPRELDNE: u32 = 0x0000_8000; -/// Disp reloc applied at run-time. -pub const DF_1_DISPRELPND: u32 = 0x0001_0000; -/// Object has no-direct binding. -pub const DF_1_NODIRECT: u32 = 0x0002_0000; -pub const DF_1_IGNMULDEF: u32 = 0x0004_0000; -pub const DF_1_NOKSYMS: u32 = 0x0008_0000; -pub const DF_1_NOHDR: u32 = 0x0010_0000; -/// Object is modified after built. -pub const DF_1_EDITED: u32 = 0x0020_0000; -pub const DF_1_NORELOC: u32 = 0x0040_0000; -/// Object has individual interposers. -pub const DF_1_SYMINTPOSE: u32 = 0x0080_0000; -/// Global auditing required. -pub const DF_1_GLOBAUDIT: u32 = 0x0100_0000; -/// Singleton symbols are used. -pub const DF_1_SINGLETON: u32 = 0x0200_0000; -pub const DF_1_STUB: u32 = 0x0400_0000; -pub const DF_1_PIE: u32 = 0x0800_0000; - -/// Version symbol information -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Versym(pub U16); - -/// Symbol is hidden. -pub const VERSYM_HIDDEN: u16 = 0x8000; -/// Symbol version index. -pub const VERSYM_VERSION: u16 = 0x7fff; - -/// Version definition sections -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Verdef { - /// Version revision - pub vd_version: U16, - /// Version information - pub vd_flags: U16, - /// Version Index - pub vd_ndx: U16, - /// Number of associated aux entries - pub vd_cnt: U16, - /// Version name hash value - pub vd_hash: U32, - /// Offset in bytes to verdaux array - pub vd_aux: U32, - /// Offset in bytes to next verdef entry - pub vd_next: U32, -} - -// Legal values for vd_version (version revision). -/// No version -pub const VER_DEF_NONE: u16 = 0; -/// Current version -pub const VER_DEF_CURRENT: u16 = 1; - -// Legal values for vd_flags (version information flags). -/// Version definition of file itself -pub const VER_FLG_BASE: u16 = 0x1; -// Legal values for vd_flags and vna_flags (version information flags). -/// Weak version identifier -pub const VER_FLG_WEAK: u16 = 0x2; - -// Versym symbol index values. -/// Symbol is local. -pub const VER_NDX_LOCAL: u16 = 0; -/// Symbol is global. -pub const VER_NDX_GLOBAL: u16 = 1; - -/// Auxiliary version information. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Verdaux { - /// Version or dependency names - pub vda_name: U32, - /// Offset in bytes to next verdaux - pub vda_next: U32, -} - -/// Version dependency. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Verneed { - /// Version of structure - pub vn_version: U16, - /// Number of associated aux entries - pub vn_cnt: U16, - /// Offset of filename for this dependency - pub vn_file: U32, - /// Offset in bytes to vernaux array - pub vn_aux: U32, - /// Offset in bytes to next verneed entry - pub vn_next: U32, -} - -// Legal values for vn_version (version revision). -/// No version -pub const VER_NEED_NONE: u16 = 0; -/// Current version -pub const VER_NEED_CURRENT: u16 = 1; - -/// Auxiliary needed version information. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Vernaux { - /// Hash value of dependency name - pub vna_hash: U32, - /// Dependency specific information - pub vna_flags: U16, - /// Version Index - pub vna_other: U16, - /// Dependency name string offset - pub vna_name: U32, - /// Offset in bytes to next vernaux entry - pub vna_next: U32, -} - -// TODO: Elf*_auxv_t, AT_* - -/// Note section entry header. -/// -/// A note consists of a header followed by a variable length name and descriptor. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct NoteHeader32 { - /// Length of the note's name. - /// - /// Some known names are defined by the `ELF_NOTE_*` constants. - pub n_namesz: U32, - /// Length of the note's descriptor. - /// - /// The content of the descriptor depends on the note name and type. - pub n_descsz: U32, - /// Type of the note. - /// - /// One of the `NT_*` constants. The note name determines which - /// `NT_*` constants are valid. - pub n_type: U32, -} - -/// Note section entry header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct NoteHeader64 { - /// Length of the note's name. - /// - /// Some known names are defined by the `ELF_NOTE_*` constants. - pub n_namesz: U32, - /// Length of the note's descriptor. - /// - /// The content of the descriptor depends on the note name and type. - pub n_descsz: U32, - /// Type of the note. - /// - /// One of the `NT_*` constants. The note name determines which - /// `NT_*` constants are valid. - pub n_type: U32, -} - -/// Solaris entries in the note section have this name. -pub const ELF_NOTE_SOLARIS: &[u8] = b"SUNW Solaris"; - -// Values for `n_type` when the name is `ELF_NOTE_SOLARIS`. -/// Desired pagesize for the binary. -pub const NT_SOLARIS_PAGESIZE_HINT: u32 = 1; - -/// GNU entries in the note section have this name. -pub const ELF_NOTE_GNU: &[u8] = b"GNU"; - -/// Go entries in the note section have this name. -// See https://go-review.googlesource.com/9520 and https://go-review.googlesource.com/10704. -pub const ELF_NOTE_GO: &[u8] = b"Go"; - -// Note types for `ELF_NOTE_GNU`. - -/// ABI information. -/// -/// The descriptor consists of words: -/// - word 0: OS descriptor -/// - word 1: major version of the ABI -/// - word 2: minor version of the ABI -/// - word 3: subminor version of the ABI -pub const NT_GNU_ABI_TAG: u32 = 1; - -/// OS descriptor for `NT_GNU_ABI_TAG`. -pub const ELF_NOTE_OS_LINUX: u32 = 0; -/// OS descriptor for `NT_GNU_ABI_TAG`. -pub const ELF_NOTE_OS_GNU: u32 = 1; -/// OS descriptor for `NT_GNU_ABI_TAG`. -pub const ELF_NOTE_OS_SOLARIS2: u32 = 2; -/// OS descriptor for `NT_GNU_ABI_TAG`. -pub const ELF_NOTE_OS_FREEBSD: u32 = 3; - -/// Synthetic hwcap information. -/// -/// The descriptor begins with two words: -/// - word 0: number of entries -/// - word 1: bitmask of enabled entries -/// Then follow variable-length entries, one byte followed by a -/// '\0'-terminated hwcap name string. The byte gives the bit -/// number to test if enabled, (1U << bit) & bitmask. */ -pub const NT_GNU_HWCAP: u32 = 2; - -/// Build ID bits as generated by `ld --build-id`. -/// -/// The descriptor consists of any nonzero number of bytes. -pub const NT_GNU_BUILD_ID: u32 = 3; - -/// Build ID bits as generated by Go's gc compiler. -/// -/// The descriptor consists of any nonzero number of bytes. -// See https://go-review.googlesource.com/10707. -pub const NT_GO_BUILD_ID: u32 = 4; - -/// Version note generated by GNU gold containing a version string. -pub const NT_GNU_GOLD_VERSION: u32 = 4; - -/// Program property. -pub const NT_GNU_PROPERTY_TYPE_0: u32 = 5; - -// Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). - -/// Stack size. -pub const GNU_PROPERTY_STACK_SIZE: u32 = 1; -/// No copy relocation on protected data symbol. -pub const GNU_PROPERTY_NO_COPY_ON_PROTECTED: u32 = 2; - -// A 4-byte unsigned integer property: A bit is set if it is set in all -// relocatable inputs. -pub const GNU_PROPERTY_UINT32_AND_LO: u32 = 0xb0000000; -pub const GNU_PROPERTY_UINT32_AND_HI: u32 = 0xb0007fff; - -// A 4-byte unsigned integer property: A bit is set if it is set in any -// relocatable inputs. -pub const GNU_PROPERTY_UINT32_OR_LO: u32 = 0xb0008000; -pub const GNU_PROPERTY_UINT32_OR_HI: u32 = 0xb000ffff; - -/// The needed properties by the object file. */ -pub const GNU_PROPERTY_1_NEEDED: u32 = GNU_PROPERTY_UINT32_OR_LO; - -/// Set if the object file requires canonical function pointers and -/// cannot be used with copy relocation. -pub const GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS: u32 = 1 << 0; - -/// Processor-specific semantics, lo -pub const GNU_PROPERTY_LOPROC: u32 = 0xc0000000; -/// Processor-specific semantics, hi -pub const GNU_PROPERTY_HIPROC: u32 = 0xdfffffff; -/// Application-specific semantics, lo -pub const GNU_PROPERTY_LOUSER: u32 = 0xe0000000; -/// Application-specific semantics, hi -pub const GNU_PROPERTY_HIUSER: u32 = 0xffffffff; - -/// AArch64 specific GNU properties. -pub const GNU_PROPERTY_AARCH64_FEATURE_1_AND: u32 = 0xc0000000; -pub const GNU_PROPERTY_AARCH64_FEATURE_PAUTH: u32 = 0xc0000001; - -pub const GNU_PROPERTY_AARCH64_FEATURE_1_BTI: u32 = 1 << 0; -pub const GNU_PROPERTY_AARCH64_FEATURE_1_PAC: u32 = 1 << 1; - -// A 4-byte unsigned integer property: A bit is set if it is set in all -// relocatable inputs. -pub const GNU_PROPERTY_X86_UINT32_AND_LO: u32 = 0xc0000002; -pub const GNU_PROPERTY_X86_UINT32_AND_HI: u32 = 0xc0007fff; - -// A 4-byte unsigned integer property: A bit is set if it is set in any -// relocatable inputs. -pub const GNU_PROPERTY_X86_UINT32_OR_LO: u32 = 0xc0008000; -pub const GNU_PROPERTY_X86_UINT32_OR_HI: u32 = 0xc000ffff; - -// A 4-byte unsigned integer property: A bit is set if it is set in any -// relocatable inputs and the property is present in all relocatable -// inputs. -pub const GNU_PROPERTY_X86_UINT32_OR_AND_LO: u32 = 0xc0010000; -pub const GNU_PROPERTY_X86_UINT32_OR_AND_HI: u32 = 0xc0017fff; - -/// The x86 instruction sets indicated by the corresponding bits are -/// used in program. Their support in the hardware is optional. -pub const GNU_PROPERTY_X86_ISA_1_USED: u32 = 0xc0010002; -/// The x86 instruction sets indicated by the corresponding bits are -/// used in program and they must be supported by the hardware. -pub const GNU_PROPERTY_X86_ISA_1_NEEDED: u32 = 0xc0008002; -/// X86 processor-specific features used in program. -pub const GNU_PROPERTY_X86_FEATURE_1_AND: u32 = 0xc0000002; - -/// GNU_PROPERTY_X86_ISA_1_BASELINE: CMOV, CX8 (cmpxchg8b), FPU (fld), -/// MMX, OSFXSR (fxsave), SCE (syscall), SSE and SSE2. -pub const GNU_PROPERTY_X86_ISA_1_BASELINE: u32 = 1 << 0; -/// GNU_PROPERTY_X86_ISA_1_V2: GNU_PROPERTY_X86_ISA_1_BASELINE, -/// CMPXCHG16B (cmpxchg16b), LAHF-SAHF (lahf), POPCNT (popcnt), SSE3, -/// SSSE3, SSE4.1 and SSE4.2. -pub const GNU_PROPERTY_X86_ISA_1_V2: u32 = 1 << 1; -/// GNU_PROPERTY_X86_ISA_1_V3: GNU_PROPERTY_X86_ISA_1_V2, AVX, AVX2, BMI1, -/// BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE. -pub const GNU_PROPERTY_X86_ISA_1_V3: u32 = 1 << 2; -/// GNU_PROPERTY_X86_ISA_1_V4: GNU_PROPERTY_X86_ISA_1_V3, AVX512F, -/// AVX512BW, AVX512CD, AVX512DQ and AVX512VL. -pub const GNU_PROPERTY_X86_ISA_1_V4: u32 = 1 << 3; - -/// This indicates that all executable sections are compatible with IBT. -pub const GNU_PROPERTY_X86_FEATURE_1_IBT: u32 = 1 << 0; -/// This indicates that all executable sections are compatible with SHSTK. -pub const GNU_PROPERTY_X86_FEATURE_1_SHSTK: u32 = 1 << 1; - -// TODO: Elf*_Move - -/// Header of `SHT_HASH` section. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct HashHeader { - /// The number of hash buckets. - pub bucket_count: U32, - /// The number of chain values. - pub chain_count: U32, - // Array of hash bucket start indices. - // buckets: U32[bucket_count] - // Array of hash chain links. An index of 0 terminates the chain. - // chains: U32[chain_count] -} - -/// Calculate the SysV hash for a symbol name. -/// -/// Used for `SHT_HASH`. -pub fn hash(name: &[u8]) -> u32 { - let mut hash = 0u32; - for byte in name { - hash = hash.wrapping_mul(16).wrapping_add(u32::from(*byte)); - hash ^= (hash >> 24) & 0xf0; - } - hash & 0xfff_ffff -} - -/// Header of `SHT_GNU_HASH` section. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct GnuHashHeader { - /// The number of hash buckets. - pub bucket_count: U32, - /// The symbol table index of the first symbol in the hash. - pub symbol_base: U32, - /// The number of words in the bloom filter. - /// - /// Must be a non-zero power of 2. - pub bloom_count: U32, - /// The bit shift count for the bloom filter. - pub bloom_shift: U32, - // Array of bloom filter words. - // bloom_filters: U32[bloom_count] or U64[bloom_count] - // Array of hash bucket start indices. - // buckets: U32[bucket_count] - // Array of hash values, one for each symbol starting at symbol_base. - // values: U32[symbol_count] -} - -/// Calculate the GNU hash for a symbol name. -/// -/// Used for `SHT_GNU_HASH`. -pub fn gnu_hash(name: &[u8]) -> u32 { - let mut hash = 5381u32; - for byte in name { - hash = hash.wrapping_mul(33).wrapping_add(u32::from(*byte)); - } - hash -} - -// Motorola 68k specific definitions. - -// m68k values for `Rel*::r_type`. - -/// No reloc -pub const R_68K_NONE: u32 = 0; -/// Direct 32 bit -pub const R_68K_32: u32 = 1; -/// Direct 16 bit -pub const R_68K_16: u32 = 2; -/// Direct 8 bit -pub const R_68K_8: u32 = 3; -/// PC relative 32 bit -pub const R_68K_PC32: u32 = 4; -/// PC relative 16 bit -pub const R_68K_PC16: u32 = 5; -/// PC relative 8 bit -pub const R_68K_PC8: u32 = 6; -/// 32 bit PC relative GOT entry -pub const R_68K_GOT32: u32 = 7; -/// 16 bit PC relative GOT entry -pub const R_68K_GOT16: u32 = 8; -/// 8 bit PC relative GOT entry -pub const R_68K_GOT8: u32 = 9; -/// 32 bit GOT offset -pub const R_68K_GOT32O: u32 = 10; -/// 16 bit GOT offset -pub const R_68K_GOT16O: u32 = 11; -/// 8 bit GOT offset -pub const R_68K_GOT8O: u32 = 12; -/// 32 bit PC relative PLT address -pub const R_68K_PLT32: u32 = 13; -/// 16 bit PC relative PLT address -pub const R_68K_PLT16: u32 = 14; -/// 8 bit PC relative PLT address -pub const R_68K_PLT8: u32 = 15; -/// 32 bit PLT offset -pub const R_68K_PLT32O: u32 = 16; -/// 16 bit PLT offset -pub const R_68K_PLT16O: u32 = 17; -/// 8 bit PLT offset -pub const R_68K_PLT8O: u32 = 18; -/// Copy symbol at runtime -pub const R_68K_COPY: u32 = 19; -/// Create GOT entry -pub const R_68K_GLOB_DAT: u32 = 20; -/// Create PLT entry -pub const R_68K_JMP_SLOT: u32 = 21; -/// Adjust by program base -pub const R_68K_RELATIVE: u32 = 22; -/// 32 bit GOT offset for GD -pub const R_68K_TLS_GD32: u32 = 25; -/// 16 bit GOT offset for GD -pub const R_68K_TLS_GD16: u32 = 26; -/// 8 bit GOT offset for GD -pub const R_68K_TLS_GD8: u32 = 27; -/// 32 bit GOT offset for LDM -pub const R_68K_TLS_LDM32: u32 = 28; -/// 16 bit GOT offset for LDM -pub const R_68K_TLS_LDM16: u32 = 29; -/// 8 bit GOT offset for LDM -pub const R_68K_TLS_LDM8: u32 = 30; -/// 32 bit module-relative offset -pub const R_68K_TLS_LDO32: u32 = 31; -/// 16 bit module-relative offset -pub const R_68K_TLS_LDO16: u32 = 32; -/// 8 bit module-relative offset -pub const R_68K_TLS_LDO8: u32 = 33; -/// 32 bit GOT offset for IE -pub const R_68K_TLS_IE32: u32 = 34; -/// 16 bit GOT offset for IE -pub const R_68K_TLS_IE16: u32 = 35; -/// 8 bit GOT offset for IE -pub const R_68K_TLS_IE8: u32 = 36; -/// 32 bit offset relative to static TLS block -pub const R_68K_TLS_LE32: u32 = 37; -/// 16 bit offset relative to static TLS block -pub const R_68K_TLS_LE16: u32 = 38; -/// 8 bit offset relative to static TLS block -pub const R_68K_TLS_LE8: u32 = 39; -/// 32 bit module number -pub const R_68K_TLS_DTPMOD32: u32 = 40; -/// 32 bit module-relative offset -pub const R_68K_TLS_DTPREL32: u32 = 41; -/// 32 bit TP-relative offset -pub const R_68K_TLS_TPREL32: u32 = 42; - -// Intel 80386 specific definitions. - -// i386 values for `Rel*::r_type`. - -/// No reloc -pub const R_386_NONE: u32 = 0; -/// Direct 32 bit -pub const R_386_32: u32 = 1; -/// PC relative 32 bit -pub const R_386_PC32: u32 = 2; -/// 32 bit GOT entry -pub const R_386_GOT32: u32 = 3; -/// 32 bit PLT address -pub const R_386_PLT32: u32 = 4; -/// Copy symbol at runtime -pub const R_386_COPY: u32 = 5; -/// Create GOT entry -pub const R_386_GLOB_DAT: u32 = 6; -/// Create PLT entry -pub const R_386_JMP_SLOT: u32 = 7; -/// Adjust by program base -pub const R_386_RELATIVE: u32 = 8; -/// 32 bit offset to GOT -pub const R_386_GOTOFF: u32 = 9; -/// 32 bit PC relative offset to GOT -pub const R_386_GOTPC: u32 = 10; -/// Direct 32 bit PLT address -pub const R_386_32PLT: u32 = 11; -/// Offset in static TLS block -pub const R_386_TLS_TPOFF: u32 = 14; -/// Address of GOT entry for static TLS block offset -pub const R_386_TLS_IE: u32 = 15; -/// GOT entry for static TLS block offset -pub const R_386_TLS_GOTIE: u32 = 16; -/// Offset relative to static TLS block -pub const R_386_TLS_LE: u32 = 17; -/// Direct 32 bit for GNU version of general dynamic thread local data -pub const R_386_TLS_GD: u32 = 18; -/// Direct 32 bit for GNU version of local dynamic thread local data in LE code -pub const R_386_TLS_LDM: u32 = 19; -/// Direct 16 bit -pub const R_386_16: u32 = 20; -/// PC relative 16 bit -pub const R_386_PC16: u32 = 21; -/// Direct 8 bit -pub const R_386_8: u32 = 22; -/// PC relative 8 bit -pub const R_386_PC8: u32 = 23; -/// Direct 32 bit for general dynamic thread local data -pub const R_386_TLS_GD_32: u32 = 24; -/// Tag for pushl in GD TLS code -pub const R_386_TLS_GD_PUSH: u32 = 25; -/// Relocation for call to __tls_get_addr() -pub const R_386_TLS_GD_CALL: u32 = 26; -/// Tag for popl in GD TLS code -pub const R_386_TLS_GD_POP: u32 = 27; -/// Direct 32 bit for local dynamic thread local data in LE code -pub const R_386_TLS_LDM_32: u32 = 28; -/// Tag for pushl in LDM TLS code -pub const R_386_TLS_LDM_PUSH: u32 = 29; -/// Relocation for call to __tls_get_addr() in LDM code -pub const R_386_TLS_LDM_CALL: u32 = 30; -/// Tag for popl in LDM TLS code -pub const R_386_TLS_LDM_POP: u32 = 31; -/// Offset relative to TLS block -pub const R_386_TLS_LDO_32: u32 = 32; -/// GOT entry for negated static TLS block offset -pub const R_386_TLS_IE_32: u32 = 33; -/// Negated offset relative to static TLS block -pub const R_386_TLS_LE_32: u32 = 34; -/// ID of module containing symbol -pub const R_386_TLS_DTPMOD32: u32 = 35; -/// Offset in TLS block -pub const R_386_TLS_DTPOFF32: u32 = 36; -/// Negated offset in static TLS block -pub const R_386_TLS_TPOFF32: u32 = 37; -/// 32-bit symbol size -pub const R_386_SIZE32: u32 = 38; -/// GOT offset for TLS descriptor. -pub const R_386_TLS_GOTDESC: u32 = 39; -/// Marker of call through TLS descriptor for relaxation. -pub const R_386_TLS_DESC_CALL: u32 = 40; -/// TLS descriptor containing pointer to code and to argument, returning the TLS offset for the symbol. -pub const R_386_TLS_DESC: u32 = 41; -/// Adjust indirectly by program base -pub const R_386_IRELATIVE: u32 = 42; -/// Load from 32 bit GOT entry, relaxable. -pub const R_386_GOT32X: u32 = 43; - -// ADI SHARC specific definitions - -// SHARC values for `Rel*::r_type` - -/// 24-bit absolute address in bits 23:0 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 25a (PC_DIRECT) -pub const R_SHARC_ADDR24_V3: u32 = 0x0b; - -/// 32-bit absolute address in bits 31:0 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 14a -/// * Type 14d -/// * Type 15a -/// * Type 16a -/// * Type 17a -/// * Type 18a -/// * Type 19a -pub const R_SHARC_ADDR32_V3: u32 = 0x0c; - -/// 32-bit absolute address in bits 31:0 of a 32-bit data location -/// -/// Represented with `RelocationEncoding::Generic` -pub const R_SHARC_ADDR_VAR_V3: u32 = 0x0d; - -/// 6-bit PC-relative address in bits 32:27 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 9a -/// * Type 10a -pub const R_SHARC_PCRSHORT_V3: u32 = 0x0e; - -/// 24-bit PC-relative address in bits 23:0 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 8a -/// * Type 12a (truncated to 23 bits after relocation) -/// * Type 13a (truncated to 23 bits after relocation) -/// * Type 25a (PC Relative) -pub const R_SHARC_PCRLONG_V3: u32 = 0x0f; - -/// 6-bit absolute address in bits 32:27 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 4a -/// * Type 4b -/// * Type 4d -pub const R_SHARC_DATA6_V3: u32 = 0x10; - -/// 16-bit absolute address in bits 39:24 of a 48-bit instr -/// -/// Targets: -/// -/// * Type 12a -pub const R_SHARC_DATA16_V3: u32 = 0x11; - -/// 6-bit absolute address into bits 16:11 of a 32-bit instr -/// -/// Targets: -/// -/// * Type 4b -pub const R_SHARC_DATA6_VISA_V3: u32 = 0x12; - -/// 7-bit absolute address into bits 6:0 of a 32-bit instr -pub const R_SHARC_DATA7_VISA_V3: u32 = 0x13; - -/// 16-bit absolute address into bits 15:0 of a 32-bit instr -pub const R_SHARC_DATA16_VISA_V3: u32 = 0x14; - -/// 6-bit PC-relative address into bits 16:11 of a Type B -/// -/// Targets: -/// -/// * Type 9b -pub const R_SHARC_PCR6_VISA_V3: u32 = 0x17; - -/// 16-bit absolute address into bits 15:0 of a 16-bit location. -/// -/// Represented with `RelocationEncoding::Generic` -pub const R_SHARC_ADDR_VAR16_V3: u32 = 0x19; - -pub const R_SHARC_CALC_PUSH_ADDR: u32 = 0xe0; -pub const R_SHARC_CALC_PUSH_ADDEND: u32 = 0xe1; -pub const R_SHARC_CALC_ADD: u32 = 0xe2; -pub const R_SHARC_CALC_SUB: u32 = 0xe3; -pub const R_SHARC_CALC_MUL: u32 = 0xe4; -pub const R_SHARC_CALC_DIV: u32 = 0xe5; -pub const R_SHARC_CALC_MOD: u32 = 0xe6; -pub const R_SHARC_CALC_LSHIFT: u32 = 0xe7; -pub const R_SHARC_CALC_RSHIFT: u32 = 0xe8; -pub const R_SHARC_CALC_AND: u32 = 0xe9; -pub const R_SHARC_CALC_OR: u32 = 0xea; -pub const R_SHARC_CALC_XOR: u32 = 0xeb; -pub const R_SHARC_CALC_PUSH_LEN: u32 = 0xec; -pub const R_SHARC_CALC_NOT: u32 = 0xf6; - -// SHARC values for `SectionHeader*::sh_type`. - -/// .adi.attributes -pub const SHT_SHARC_ADI_ATTRIBUTES: u32 = SHT_LOPROC + 0x2; - -// SUN SPARC specific definitions. - -// SPARC values for `st_type` component of `Sym*::st_info`. - -/// Global register reserved to app. -pub const STT_SPARC_REGISTER: u8 = 13; - -// SPARC values for `FileHeader64::e_flags`. - -pub const EF_SPARCV9_MM: u32 = 3; -pub const EF_SPARCV9_TSO: u32 = 0; -pub const EF_SPARCV9_PSO: u32 = 1; -pub const EF_SPARCV9_RMO: u32 = 2; -/// little endian data -pub const EF_SPARC_LEDATA: u32 = 0x80_0000; -pub const EF_SPARC_EXT_MASK: u32 = 0xFF_FF00; -/// generic V8+ features -pub const EF_SPARC_32PLUS: u32 = 0x00_0100; -/// Sun UltraSPARC1 extensions -pub const EF_SPARC_SUN_US1: u32 = 0x00_0200; -/// HAL R1 extensions -pub const EF_SPARC_HAL_R1: u32 = 0x00_0400; -/// Sun UltraSPARCIII extensions -pub const EF_SPARC_SUN_US3: u32 = 0x00_0800; - -// SPARC values for `Rel*::r_type`. - -/// No reloc -pub const R_SPARC_NONE: u32 = 0; -/// Direct 8 bit -pub const R_SPARC_8: u32 = 1; -/// Direct 16 bit -pub const R_SPARC_16: u32 = 2; -/// Direct 32 bit -pub const R_SPARC_32: u32 = 3; -/// PC relative 8 bit -pub const R_SPARC_DISP8: u32 = 4; -/// PC relative 16 bit -pub const R_SPARC_DISP16: u32 = 5; -/// PC relative 32 bit -pub const R_SPARC_DISP32: u32 = 6; -/// PC relative 30 bit shifted -pub const R_SPARC_WDISP30: u32 = 7; -/// PC relative 22 bit shifted -pub const R_SPARC_WDISP22: u32 = 8; -/// High 22 bit -pub const R_SPARC_HI22: u32 = 9; -/// Direct 22 bit -pub const R_SPARC_22: u32 = 10; -/// Direct 13 bit -pub const R_SPARC_13: u32 = 11; -/// Truncated 10 bit -pub const R_SPARC_LO10: u32 = 12; -/// Truncated 10 bit GOT entry -pub const R_SPARC_GOT10: u32 = 13; -/// 13 bit GOT entry -pub const R_SPARC_GOT13: u32 = 14; -/// 22 bit GOT entry shifted -pub const R_SPARC_GOT22: u32 = 15; -/// PC relative 10 bit truncated -pub const R_SPARC_PC10: u32 = 16; -/// PC relative 22 bit shifted -pub const R_SPARC_PC22: u32 = 17; -/// 30 bit PC relative PLT address -pub const R_SPARC_WPLT30: u32 = 18; -/// Copy symbol at runtime -pub const R_SPARC_COPY: u32 = 19; -/// Create GOT entry -pub const R_SPARC_GLOB_DAT: u32 = 20; -/// Create PLT entry -pub const R_SPARC_JMP_SLOT: u32 = 21; -/// Adjust by program base -pub const R_SPARC_RELATIVE: u32 = 22; -/// Direct 32 bit unaligned -pub const R_SPARC_UA32: u32 = 23; - -// Sparc64 values for `Rel*::r_type`. - -/// Direct 32 bit ref to PLT entry -pub const R_SPARC_PLT32: u32 = 24; -/// High 22 bit PLT entry -pub const R_SPARC_HIPLT22: u32 = 25; -/// Truncated 10 bit PLT entry -pub const R_SPARC_LOPLT10: u32 = 26; -/// PC rel 32 bit ref to PLT entry -pub const R_SPARC_PCPLT32: u32 = 27; -/// PC rel high 22 bit PLT entry -pub const R_SPARC_PCPLT22: u32 = 28; -/// PC rel trunc 10 bit PLT entry -pub const R_SPARC_PCPLT10: u32 = 29; -/// Direct 10 bit -pub const R_SPARC_10: u32 = 30; -/// Direct 11 bit -pub const R_SPARC_11: u32 = 31; -/// Direct 64 bit -pub const R_SPARC_64: u32 = 32; -/// 10bit with secondary 13bit addend -pub const R_SPARC_OLO10: u32 = 33; -/// Top 22 bits of direct 64 bit -pub const R_SPARC_HH22: u32 = 34; -/// High middle 10 bits of ... -pub const R_SPARC_HM10: u32 = 35; -/// Low middle 22 bits of ... -pub const R_SPARC_LM22: u32 = 36; -/// Top 22 bits of pc rel 64 bit -pub const R_SPARC_PC_HH22: u32 = 37; -/// High middle 10 bit of ... -pub const R_SPARC_PC_HM10: u32 = 38; -/// Low miggle 22 bits of ... -pub const R_SPARC_PC_LM22: u32 = 39; -/// PC relative 16 bit shifted -pub const R_SPARC_WDISP16: u32 = 40; -/// PC relative 19 bit shifted -pub const R_SPARC_WDISP19: u32 = 41; -/// was part of v9 ABI but was removed -pub const R_SPARC_GLOB_JMP: u32 = 42; -/// Direct 7 bit -pub const R_SPARC_7: u32 = 43; -/// Direct 5 bit -pub const R_SPARC_5: u32 = 44; -/// Direct 6 bit -pub const R_SPARC_6: u32 = 45; -/// PC relative 64 bit -pub const R_SPARC_DISP64: u32 = 46; -/// Direct 64 bit ref to PLT entry -pub const R_SPARC_PLT64: u32 = 47; -/// High 22 bit complemented -pub const R_SPARC_HIX22: u32 = 48; -/// Truncated 11 bit complemented -pub const R_SPARC_LOX10: u32 = 49; -/// Direct high 12 of 44 bit -pub const R_SPARC_H44: u32 = 50; -/// Direct mid 22 of 44 bit -pub const R_SPARC_M44: u32 = 51; -/// Direct low 10 of 44 bit -pub const R_SPARC_L44: u32 = 52; -/// Global register usage -pub const R_SPARC_REGISTER: u32 = 53; -/// Direct 64 bit unaligned -pub const R_SPARC_UA64: u32 = 54; -/// Direct 16 bit unaligned -pub const R_SPARC_UA16: u32 = 55; -pub const R_SPARC_TLS_GD_HI22: u32 = 56; -pub const R_SPARC_TLS_GD_LO10: u32 = 57; -pub const R_SPARC_TLS_GD_ADD: u32 = 58; -pub const R_SPARC_TLS_GD_CALL: u32 = 59; -pub const R_SPARC_TLS_LDM_HI22: u32 = 60; -pub const R_SPARC_TLS_LDM_LO10: u32 = 61; -pub const R_SPARC_TLS_LDM_ADD: u32 = 62; -pub const R_SPARC_TLS_LDM_CALL: u32 = 63; -pub const R_SPARC_TLS_LDO_HIX22: u32 = 64; -pub const R_SPARC_TLS_LDO_LOX10: u32 = 65; -pub const R_SPARC_TLS_LDO_ADD: u32 = 66; -pub const R_SPARC_TLS_IE_HI22: u32 = 67; -pub const R_SPARC_TLS_IE_LO10: u32 = 68; -pub const R_SPARC_TLS_IE_LD: u32 = 69; -pub const R_SPARC_TLS_IE_LDX: u32 = 70; -pub const R_SPARC_TLS_IE_ADD: u32 = 71; -pub const R_SPARC_TLS_LE_HIX22: u32 = 72; -pub const R_SPARC_TLS_LE_LOX10: u32 = 73; -pub const R_SPARC_TLS_DTPMOD32: u32 = 74; -pub const R_SPARC_TLS_DTPMOD64: u32 = 75; -pub const R_SPARC_TLS_DTPOFF32: u32 = 76; -pub const R_SPARC_TLS_DTPOFF64: u32 = 77; -pub const R_SPARC_TLS_TPOFF32: u32 = 78; -pub const R_SPARC_TLS_TPOFF64: u32 = 79; -pub const R_SPARC_GOTDATA_HIX22: u32 = 80; -pub const R_SPARC_GOTDATA_LOX10: u32 = 81; -pub const R_SPARC_GOTDATA_OP_HIX22: u32 = 82; -pub const R_SPARC_GOTDATA_OP_LOX10: u32 = 83; -pub const R_SPARC_GOTDATA_OP: u32 = 84; -pub const R_SPARC_H34: u32 = 85; -pub const R_SPARC_SIZE32: u32 = 86; -pub const R_SPARC_SIZE64: u32 = 87; -pub const R_SPARC_WDISP10: u32 = 88; -pub const R_SPARC_JMP_IREL: u32 = 248; -pub const R_SPARC_IRELATIVE: u32 = 249; -pub const R_SPARC_GNU_VTINHERIT: u32 = 250; -pub const R_SPARC_GNU_VTENTRY: u32 = 251; -pub const R_SPARC_REV32: u32 = 252; - -// Sparc64 values for `Dyn32::d_tag`. - -pub const DT_SPARC_REGISTER: u32 = 0x7000_0001; - -// MIPS R3000 specific definitions. - -// MIPS values for `FileHeader32::e_flags`. - -/// A .noreorder directive was used. -pub const EF_MIPS_NOREORDER: u32 = 1; -/// Contains PIC code. -pub const EF_MIPS_PIC: u32 = 2; -/// Uses PIC calling sequence. -pub const EF_MIPS_CPIC: u32 = 4; -pub const EF_MIPS_XGOT: u32 = 8; -pub const EF_MIPS_64BIT_WHIRL: u32 = 16; -pub const EF_MIPS_ABI2: u32 = 32; -pub const EF_MIPS_ABI_ON32: u32 = 64; -/// Uses FP64 (12 callee-saved). -pub const EF_MIPS_FP64: u32 = 512; -/// Uses IEEE 754-2008 NaN encoding. -pub const EF_MIPS_NAN2008: u32 = 1024; -/// MIPS architecture level. -pub const EF_MIPS_ARCH: u32 = 0xf000_0000; - -/// The first MIPS 32 bit ABI -pub const EF_MIPS_ABI_O32: u32 = 0x0000_1000; -/// O32 ABI extended for 64-bit architectures -pub const EF_MIPS_ABI_O64: u32 = 0x0000_2000; -/// EABI in 32-bit mode -pub const EF_MIPS_ABI_EABI32: u32 = 0x0000_3000; -/// EABI in 64-bit mode -pub const EF_MIPS_ABI_EABI64: u32 = 0x0000_4000; -/// Mask for selecting EF_MIPS_ABI_ variant -pub const EF_MIPS_ABI: u32 = 0x0000_f000; - -// Legal values for MIPS architecture level. - -/// -mips1 code. -pub const EF_MIPS_ARCH_1: u32 = 0x0000_0000; -/// -mips2 code. -pub const EF_MIPS_ARCH_2: u32 = 0x1000_0000; -/// -mips3 code. -pub const EF_MIPS_ARCH_3: u32 = 0x2000_0000; -/// -mips4 code. -pub const EF_MIPS_ARCH_4: u32 = 0x3000_0000; -/// -mips5 code. -pub const EF_MIPS_ARCH_5: u32 = 0x4000_0000; -/// MIPS32 code. -pub const EF_MIPS_ARCH_32: u32 = 0x5000_0000; -/// MIPS64 code. -pub const EF_MIPS_ARCH_64: u32 = 0x6000_0000; -/// MIPS32r2 code. -pub const EF_MIPS_ARCH_32R2: u32 = 0x7000_0000; -/// MIPS64r2 code. -pub const EF_MIPS_ARCH_64R2: u32 = 0x8000_0000; -/// MIPS32r6 code -pub const EF_MIPS_ARCH_32R6: u32 = 0x9000_0000; -/// MIPS64r6 code -pub const EF_MIPS_ARCH_64R6: u32 = 0xa000_0000; - -// MIPS values for `Sym32::st_shndx`. - -/// Allocated common symbols. -pub const SHN_MIPS_ACOMMON: u16 = 0xff00; -/// Allocated test symbols. -pub const SHN_MIPS_TEXT: u16 = 0xff01; -/// Allocated data symbols. -pub const SHN_MIPS_DATA: u16 = 0xff02; -/// Small common symbols. -pub const SHN_MIPS_SCOMMON: u16 = 0xff03; -/// Small undefined symbols. -pub const SHN_MIPS_SUNDEFINED: u16 = 0xff04; - -// MIPS values for `SectionHeader32::sh_type`. - -/// Shared objects used in link. -pub const SHT_MIPS_LIBLIST: u32 = 0x7000_0000; -pub const SHT_MIPS_MSYM: u32 = 0x7000_0001; -/// Conflicting symbols. -pub const SHT_MIPS_CONFLICT: u32 = 0x7000_0002; -/// Global data area sizes. -pub const SHT_MIPS_GPTAB: u32 = 0x7000_0003; -/// Reserved for SGI/MIPS compilers -pub const SHT_MIPS_UCODE: u32 = 0x7000_0004; -/// MIPS ECOFF debugging info. -pub const SHT_MIPS_DEBUG: u32 = 0x7000_0005; -/// Register usage information. -pub const SHT_MIPS_REGINFO: u32 = 0x7000_0006; -pub const SHT_MIPS_PACKAGE: u32 = 0x7000_0007; -pub const SHT_MIPS_PACKSYM: u32 = 0x7000_0008; -pub const SHT_MIPS_RELD: u32 = 0x7000_0009; -pub const SHT_MIPS_IFACE: u32 = 0x7000_000b; -pub const SHT_MIPS_CONTENT: u32 = 0x7000_000c; -/// Miscellaneous options. -pub const SHT_MIPS_OPTIONS: u32 = 0x7000_000d; -pub const SHT_MIPS_SHDR: u32 = 0x7000_0010; -pub const SHT_MIPS_FDESC: u32 = 0x7000_0011; -pub const SHT_MIPS_EXTSYM: u32 = 0x7000_0012; -pub const SHT_MIPS_DENSE: u32 = 0x7000_0013; -pub const SHT_MIPS_PDESC: u32 = 0x7000_0014; -pub const SHT_MIPS_LOCSYM: u32 = 0x7000_0015; -pub const SHT_MIPS_AUXSYM: u32 = 0x7000_0016; -pub const SHT_MIPS_OPTSYM: u32 = 0x7000_0017; -pub const SHT_MIPS_LOCSTR: u32 = 0x7000_0018; -pub const SHT_MIPS_LINE: u32 = 0x7000_0019; -pub const SHT_MIPS_RFDESC: u32 = 0x7000_001a; -pub const SHT_MIPS_DELTASYM: u32 = 0x7000_001b; -pub const SHT_MIPS_DELTAINST: u32 = 0x7000_001c; -pub const SHT_MIPS_DELTACLASS: u32 = 0x7000_001d; -/// DWARF debugging information. -pub const SHT_MIPS_DWARF: u32 = 0x7000_001e; -pub const SHT_MIPS_DELTADECL: u32 = 0x7000_001f; -pub const SHT_MIPS_SYMBOL_LIB: u32 = 0x7000_0020; -/// Event section. -pub const SHT_MIPS_EVENTS: u32 = 0x7000_0021; -pub const SHT_MIPS_TRANSLATE: u32 = 0x7000_0022; -pub const SHT_MIPS_PIXIE: u32 = 0x7000_0023; -pub const SHT_MIPS_XLATE: u32 = 0x7000_0024; -pub const SHT_MIPS_XLATE_DEBUG: u32 = 0x7000_0025; -pub const SHT_MIPS_WHIRL: u32 = 0x7000_0026; -pub const SHT_MIPS_EH_REGION: u32 = 0x7000_0027; -pub const SHT_MIPS_XLATE_OLD: u32 = 0x7000_0028; -pub const SHT_MIPS_PDR_EXCEPTION: u32 = 0x7000_0029; - -// MIPS values for `SectionHeader32::sh_flags`. - -/// Must be in global data area. -pub const SHF_MIPS_GPREL: u32 = 0x1000_0000; -pub const SHF_MIPS_MERGE: u32 = 0x2000_0000; -pub const SHF_MIPS_ADDR: u32 = 0x4000_0000; -pub const SHF_MIPS_STRINGS: u32 = 0x8000_0000; -pub const SHF_MIPS_NOSTRIP: u32 = 0x0800_0000; -pub const SHF_MIPS_LOCAL: u32 = 0x0400_0000; -pub const SHF_MIPS_NAMES: u32 = 0x0200_0000; -pub const SHF_MIPS_NODUPE: u32 = 0x0100_0000; - -// MIPS values for `Sym32::st_other`. - -pub const STO_MIPS_PLT: u8 = 0x8; -/// Only valid for `STB_MIPS_SPLIT_COMMON`. -pub const STO_MIPS_SC_ALIGN_UNUSED: u8 = 0xff; - -// MIPS values for `Sym32::st_info'. -pub const STB_MIPS_SPLIT_COMMON: u8 = 13; - -// Entries found in sections of type `SHT_MIPS_GPTAB`. - -// TODO: Elf32_gptab, Elf32_RegInfo, Elf_Options - -// Values for `Elf_Options::kind`. - -/// Undefined. -pub const ODK_NULL: u32 = 0; -/// Register usage information. -pub const ODK_REGINFO: u32 = 1; -/// Exception processing options. -pub const ODK_EXCEPTIONS: u32 = 2; -/// Section padding options. -pub const ODK_PAD: u32 = 3; -/// Hardware workarounds performed -pub const ODK_HWPATCH: u32 = 4; -/// record the fill value used by the linker. -pub const ODK_FILL: u32 = 5; -/// reserve space for desktop tools to write. -pub const ODK_TAGS: u32 = 6; -/// HW workarounds. 'AND' bits when merging. -pub const ODK_HWAND: u32 = 7; -/// HW workarounds. 'OR' bits when merging. -pub const ODK_HWOR: u32 = 8; - -// Values for `Elf_Options::info` for `ODK_EXCEPTIONS` entries. - -/// FPE's which MUST be enabled. -pub const OEX_FPU_MIN: u32 = 0x1f; -/// FPE's which MAY be enabled. -pub const OEX_FPU_MAX: u32 = 0x1f00; -/// page zero must be mapped. -pub const OEX_PAGE0: u32 = 0x10000; -/// Force sequential memory mode? -pub const OEX_SMM: u32 = 0x20000; -/// Force floating point debug mode? -pub const OEX_FPDBUG: u32 = 0x40000; -pub const OEX_PRECISEFP: u32 = OEX_FPDBUG; -/// Dismiss invalid address faults? -pub const OEX_DISMISS: u32 = 0x80000; - -pub const OEX_FPU_INVAL: u32 = 0x10; -pub const OEX_FPU_DIV0: u32 = 0x08; -pub const OEX_FPU_OFLO: u32 = 0x04; -pub const OEX_FPU_UFLO: u32 = 0x02; -pub const OEX_FPU_INEX: u32 = 0x01; - -// Masks for `Elf_Options::info` for an `ODK_HWPATCH` entry. */ -/// R4000 end-of-page patch. -pub const OHW_R4KEOP: u32 = 0x1; -/// may need R8000 prefetch patch. -pub const OHW_R8KPFETCH: u32 = 0x2; -/// R5000 end-of-page patch. -pub const OHW_R5KEOP: u32 = 0x4; -/// R5000 cvt.\[ds\].l bug. clean=1. -pub const OHW_R5KCVTL: u32 = 0x8; - -pub const OPAD_PREFIX: u32 = 0x1; -pub const OPAD_POSTFIX: u32 = 0x2; -pub const OPAD_SYMBOL: u32 = 0x4; - -// Entries found in sections of type `SHT_MIPS_OPTIONS`. - -// TODO: Elf_Options_Hw - -// Masks for `ElfOptions::info` for `ODK_HWAND` and `ODK_HWOR` entries. - -pub const OHWA0_R4KEOP_CHECKED: u32 = 0x0000_0001; -pub const OHWA1_R4KEOP_CLEAN: u32 = 0x0000_0002; - -// MIPS values for `Rel*::r_type`. - -/// No reloc -pub const R_MIPS_NONE: u32 = 0; -/// Direct 16 bit -pub const R_MIPS_16: u32 = 1; -/// Direct 32 bit -pub const R_MIPS_32: u32 = 2; -/// PC relative 32 bit -pub const R_MIPS_REL32: u32 = 3; -/// Direct 26 bit shifted -pub const R_MIPS_26: u32 = 4; -/// High 16 bit -pub const R_MIPS_HI16: u32 = 5; -/// Low 16 bit -pub const R_MIPS_LO16: u32 = 6; -/// GP relative 16 bit -pub const R_MIPS_GPREL16: u32 = 7; -/// 16 bit literal entry -pub const R_MIPS_LITERAL: u32 = 8; -/// 16 bit GOT entry -pub const R_MIPS_GOT16: u32 = 9; -/// PC relative 16 bit -pub const R_MIPS_PC16: u32 = 10; -/// 16 bit GOT entry for function -pub const R_MIPS_CALL16: u32 = 11; -/// GP relative 32 bit -pub const R_MIPS_GPREL32: u32 = 12; - -pub const R_MIPS_SHIFT5: u32 = 16; -pub const R_MIPS_SHIFT6: u32 = 17; -pub const R_MIPS_64: u32 = 18; -pub const R_MIPS_GOT_DISP: u32 = 19; -pub const R_MIPS_GOT_PAGE: u32 = 20; -pub const R_MIPS_GOT_OFST: u32 = 21; -pub const R_MIPS_GOT_HI16: u32 = 22; -pub const R_MIPS_GOT_LO16: u32 = 23; -pub const R_MIPS_SUB: u32 = 24; -pub const R_MIPS_INSERT_A: u32 = 25; -pub const R_MIPS_INSERT_B: u32 = 26; -pub const R_MIPS_DELETE: u32 = 27; -pub const R_MIPS_HIGHER: u32 = 28; -pub const R_MIPS_HIGHEST: u32 = 29; -pub const R_MIPS_CALL_HI16: u32 = 30; -pub const R_MIPS_CALL_LO16: u32 = 31; -pub const R_MIPS_SCN_DISP: u32 = 32; -pub const R_MIPS_REL16: u32 = 33; -pub const R_MIPS_ADD_IMMEDIATE: u32 = 34; -pub const R_MIPS_PJUMP: u32 = 35; -pub const R_MIPS_RELGOT: u32 = 36; -pub const R_MIPS_JALR: u32 = 37; -/// Module number 32 bit -pub const R_MIPS_TLS_DTPMOD32: u32 = 38; -/// Module-relative offset 32 bit -pub const R_MIPS_TLS_DTPREL32: u32 = 39; -/// Module number 64 bit -pub const R_MIPS_TLS_DTPMOD64: u32 = 40; -/// Module-relative offset 64 bit -pub const R_MIPS_TLS_DTPREL64: u32 = 41; -/// 16 bit GOT offset for GD -pub const R_MIPS_TLS_GD: u32 = 42; -/// 16 bit GOT offset for LDM -pub const R_MIPS_TLS_LDM: u32 = 43; -/// Module-relative offset, high 16 bits -pub const R_MIPS_TLS_DTPREL_HI16: u32 = 44; -/// Module-relative offset, low 16 bits -pub const R_MIPS_TLS_DTPREL_LO16: u32 = 45; -/// 16 bit GOT offset for IE -pub const R_MIPS_TLS_GOTTPREL: u32 = 46; -/// TP-relative offset, 32 bit -pub const R_MIPS_TLS_TPREL32: u32 = 47; -/// TP-relative offset, 64 bit -pub const R_MIPS_TLS_TPREL64: u32 = 48; -/// TP-relative offset, high 16 bits -pub const R_MIPS_TLS_TPREL_HI16: u32 = 49; -/// TP-relative offset, low 16 bits -pub const R_MIPS_TLS_TPREL_LO16: u32 = 50; -pub const R_MIPS_GLOB_DAT: u32 = 51; -pub const R_MIPS_COPY: u32 = 126; -pub const R_MIPS_JUMP_SLOT: u32 = 127; - -// MIPS values for `ProgramHeader32::p_type`. - -/// Register usage information. -pub const PT_MIPS_REGINFO: u32 = 0x7000_0000; -/// Runtime procedure table. -pub const PT_MIPS_RTPROC: u32 = 0x7000_0001; -pub const PT_MIPS_OPTIONS: u32 = 0x7000_0002; -/// FP mode requirement. -pub const PT_MIPS_ABIFLAGS: u32 = 0x7000_0003; - -// MIPS values for `ProgramHeader32::p_flags`. - -pub const PF_MIPS_LOCAL: u32 = 0x1000_0000; - -// MIPS values for `Dyn32::d_tag`. - -/// Runtime linker interface version -pub const DT_MIPS_RLD_VERSION: u32 = 0x7000_0001; -/// Timestamp -pub const DT_MIPS_TIME_STAMP: u32 = 0x7000_0002; -/// Checksum -pub const DT_MIPS_ICHECKSUM: u32 = 0x7000_0003; -/// Version string (string tbl index) -pub const DT_MIPS_IVERSION: u32 = 0x7000_0004; -/// Flags -pub const DT_MIPS_FLAGS: u32 = 0x7000_0005; -/// Base address -pub const DT_MIPS_BASE_ADDRESS: u32 = 0x7000_0006; -pub const DT_MIPS_MSYM: u32 = 0x7000_0007; -/// Address of CONFLICT section -pub const DT_MIPS_CONFLICT: u32 = 0x7000_0008; -/// Address of LIBLIST section -pub const DT_MIPS_LIBLIST: u32 = 0x7000_0009; -/// Number of local GOT entries -pub const DT_MIPS_LOCAL_GOTNO: u32 = 0x7000_000a; -/// Number of CONFLICT entries -pub const DT_MIPS_CONFLICTNO: u32 = 0x7000_000b; -/// Number of LIBLIST entries -pub const DT_MIPS_LIBLISTNO: u32 = 0x7000_0010; -/// Number of DYNSYM entries -pub const DT_MIPS_SYMTABNO: u32 = 0x7000_0011; -/// First external DYNSYM -pub const DT_MIPS_UNREFEXTNO: u32 = 0x7000_0012; -/// First GOT entry in DYNSYM -pub const DT_MIPS_GOTSYM: u32 = 0x7000_0013; -/// Number of GOT page table entries -pub const DT_MIPS_HIPAGENO: u32 = 0x7000_0014; -/// Address of run time loader map. -pub const DT_MIPS_RLD_MAP: u32 = 0x7000_0016; -/// Delta C++ class definition. -pub const DT_MIPS_DELTA_CLASS: u32 = 0x7000_0017; -/// Number of entries in DT_MIPS_DELTA_CLASS. -pub const DT_MIPS_DELTA_CLASS_NO: u32 = 0x7000_0018; -/// Delta C++ class instances. -pub const DT_MIPS_DELTA_INSTANCE: u32 = 0x7000_0019; -/// Number of entries in DT_MIPS_DELTA_INSTANCE. -pub const DT_MIPS_DELTA_INSTANCE_NO: u32 = 0x7000_001a; -/// Delta relocations. -pub const DT_MIPS_DELTA_RELOC: u32 = 0x7000_001b; -/// Number of entries in DT_MIPS_DELTA_RELOC. -pub const DT_MIPS_DELTA_RELOC_NO: u32 = 0x7000_001c; -/// Delta symbols that Delta relocations refer to. -pub const DT_MIPS_DELTA_SYM: u32 = 0x7000_001d; -/// Number of entries in DT_MIPS_DELTA_SYM. -pub const DT_MIPS_DELTA_SYM_NO: u32 = 0x7000_001e; -/// Delta symbols that hold the class declaration. -pub const DT_MIPS_DELTA_CLASSSYM: u32 = 0x7000_0020; -/// Number of entries in DT_MIPS_DELTA_CLASSSYM. -pub const DT_MIPS_DELTA_CLASSSYM_NO: u32 = 0x7000_0021; -/// Flags indicating for C++ flavor. -pub const DT_MIPS_CXX_FLAGS: u32 = 0x7000_0022; -pub const DT_MIPS_PIXIE_INIT: u32 = 0x7000_0023; -pub const DT_MIPS_SYMBOL_LIB: u32 = 0x7000_0024; -pub const DT_MIPS_LOCALPAGE_GOTIDX: u32 = 0x7000_0025; -pub const DT_MIPS_LOCAL_GOTIDX: u32 = 0x7000_0026; -pub const DT_MIPS_HIDDEN_GOTIDX: u32 = 0x7000_0027; -pub const DT_MIPS_PROTECTED_GOTIDX: u32 = 0x7000_0028; -/// Address of .options. -pub const DT_MIPS_OPTIONS: u32 = 0x7000_0029; -/// Address of .interface. -pub const DT_MIPS_INTERFACE: u32 = 0x7000_002a; -pub const DT_MIPS_DYNSTR_ALIGN: u32 = 0x7000_002b; -/// Size of the .interface section. -pub const DT_MIPS_INTERFACE_SIZE: u32 = 0x7000_002c; -/// Address of rld_text_rsolve function stored in GOT. -pub const DT_MIPS_RLD_TEXT_RESOLVE_ADDR: u32 = 0x7000_002d; -/// Default suffix of dso to be added by rld on dlopen() calls. -pub const DT_MIPS_PERF_SUFFIX: u32 = 0x7000_002e; -/// (O32)Size of compact rel section. -pub const DT_MIPS_COMPACT_SIZE: u32 = 0x7000_002f; -/// GP value for aux GOTs. -pub const DT_MIPS_GP_VALUE: u32 = 0x7000_0030; -/// Address of aux .dynamic. -pub const DT_MIPS_AUX_DYNAMIC: u32 = 0x7000_0031; -/// The address of .got.plt in an executable using the new non-PIC ABI. -pub const DT_MIPS_PLTGOT: u32 = 0x7000_0032; -/// The base of the PLT in an executable using the new non-PIC ABI if that PLT is writable. For a non-writable PLT, this is omitted or has a zero value. -pub const DT_MIPS_RWPLT: u32 = 0x7000_0034; -/// An alternative description of the classic MIPS RLD_MAP that is usable in a PIE as it stores a relative offset from the address of the tag rather than an absolute address. -pub const DT_MIPS_RLD_MAP_REL: u32 = 0x7000_0035; - -// Values for `DT_MIPS_FLAGS` `Dyn32` entry. - -/// No flags -pub const RHF_NONE: u32 = 0; -/// Use quickstart -pub const RHF_QUICKSTART: u32 = 1 << 0; -/// Hash size not power of 2 -pub const RHF_NOTPOT: u32 = 1 << 1; -/// Ignore LD_LIBRARY_PATH -pub const RHF_NO_LIBRARY_REPLACEMENT: u32 = 1 << 2; -pub const RHF_NO_MOVE: u32 = 1 << 3; -pub const RHF_SGI_ONLY: u32 = 1 << 4; -pub const RHF_GUARANTEE_INIT: u32 = 1 << 5; -pub const RHF_DELTA_C_PLUS_PLUS: u32 = 1 << 6; -pub const RHF_GUARANTEE_START_INIT: u32 = 1 << 7; -pub const RHF_PIXIE: u32 = 1 << 8; -pub const RHF_DEFAULT_DELAY_LOAD: u32 = 1 << 9; -pub const RHF_REQUICKSTART: u32 = 1 << 10; -pub const RHF_REQUICKSTARTED: u32 = 1 << 11; -pub const RHF_CORD: u32 = 1 << 12; -pub const RHF_NO_UNRES_UNDEF: u32 = 1 << 13; -pub const RHF_RLD_ORDER_SAFE: u32 = 1 << 14; - -// Entries found in sections of type `SHT_MIPS_LIBLIST`. - -// TODO: Elf32_Lib, Elf64_Lib - -// Values for `Lib*::l_flags`. - -pub const LL_NONE: u32 = 0; -/// Require exact match -pub const LL_EXACT_MATCH: u32 = 1 << 0; -/// Ignore interface version -pub const LL_IGNORE_INT_VER: u32 = 1 << 1; -pub const LL_REQUIRE_MINOR: u32 = 1 << 2; -pub const LL_EXPORTS: u32 = 1 << 3; -pub const LL_DELAY_LOAD: u32 = 1 << 4; -pub const LL_DELTA: u32 = 1 << 5; - -// TODO: MIPS ABI flags - -// PA-RISC specific definitions. - -// PA-RISC values for `FileHeader32::e_flags`. - -/// Trap nil pointer dereference. -pub const EF_PARISC_TRAPNIL: u32 = 0x0001_0000; -/// Program uses arch. extensions. -pub const EF_PARISC_EXT: u32 = 0x0002_0000; -/// Program expects little endian. -pub const EF_PARISC_LSB: u32 = 0x0004_0000; -/// Program expects wide mode. -pub const EF_PARISC_WIDE: u32 = 0x0008_0000; -/// No kernel assisted branch prediction. -pub const EF_PARISC_NO_KABP: u32 = 0x0010_0000; -/// Allow lazy swapping. -pub const EF_PARISC_LAZYSWAP: u32 = 0x0040_0000; -/// Architecture version. -pub const EF_PARISC_ARCH: u32 = 0x0000_ffff; - -// Values for `EF_PARISC_ARCH'. - -/// PA-RISC 1.0 big-endian. -pub const EFA_PARISC_1_0: u32 = 0x020b; -/// PA-RISC 1.1 big-endian. -pub const EFA_PARISC_1_1: u32 = 0x0210; -/// PA-RISC 2.0 big-endian. -pub const EFA_PARISC_2_0: u32 = 0x0214; - -// PA-RISC values for `Sym*::st_shndx`. - -/// Section for tentatively declared symbols in ANSI C. -pub const SHN_PARISC_ANSI_COMMON: u16 = 0xff00; -/// Common blocks in huge model. -pub const SHN_PARISC_HUGE_COMMON: u16 = 0xff01; - -// PA-RISC values for `SectionHeader32::sh_type`. - -/// Contains product specific ext. -pub const SHT_PARISC_EXT: u32 = 0x7000_0000; -/// Unwind information. -pub const SHT_PARISC_UNWIND: u32 = 0x7000_0001; -/// Debug info for optimized code. -pub const SHT_PARISC_DOC: u32 = 0x7000_0002; - -// PA-RISC values for `SectionHeader32::sh_flags`. - -/// Section with short addressing. -pub const SHF_PARISC_SHORT: u32 = 0x2000_0000; -/// Section far from gp. -pub const SHF_PARISC_HUGE: u32 = 0x4000_0000; -/// Static branch prediction code. -pub const SHF_PARISC_SBP: u32 = 0x8000_0000; - -// PA-RISC values for `st_type` component of `Sym32::st_info`. - -/// Millicode function entry point. -pub const STT_PARISC_MILLICODE: u8 = 13; - -pub const STT_HP_OPAQUE: u8 = STT_LOOS + 0x1; -pub const STT_HP_STUB: u8 = STT_LOOS + 0x2; - -// PA-RISC values for `Rel*::r_type`. - -/// No reloc. -pub const R_PARISC_NONE: u32 = 0; -/// Direct 32-bit reference. -pub const R_PARISC_DIR32: u32 = 1; -/// Left 21 bits of eff. address. -pub const R_PARISC_DIR21L: u32 = 2; -/// Right 17 bits of eff. address. -pub const R_PARISC_DIR17R: u32 = 3; -/// 17 bits of eff. address. -pub const R_PARISC_DIR17F: u32 = 4; -/// Right 14 bits of eff. address. -pub const R_PARISC_DIR14R: u32 = 6; -/// 32-bit rel. address. -pub const R_PARISC_PCREL32: u32 = 9; -/// Left 21 bits of rel. address. -pub const R_PARISC_PCREL21L: u32 = 10; -/// Right 17 bits of rel. address. -pub const R_PARISC_PCREL17R: u32 = 11; -/// 17 bits of rel. address. -pub const R_PARISC_PCREL17F: u32 = 12; -/// Right 14 bits of rel. address. -pub const R_PARISC_PCREL14R: u32 = 14; -/// Left 21 bits of rel. address. -pub const R_PARISC_DPREL21L: u32 = 18; -/// Right 14 bits of rel. address. -pub const R_PARISC_DPREL14R: u32 = 22; -/// GP-relative, left 21 bits. -pub const R_PARISC_GPREL21L: u32 = 26; -/// GP-relative, right 14 bits. -pub const R_PARISC_GPREL14R: u32 = 30; -/// LT-relative, left 21 bits. -pub const R_PARISC_LTOFF21L: u32 = 34; -/// LT-relative, right 14 bits. -pub const R_PARISC_LTOFF14R: u32 = 38; -/// 32 bits section rel. address. -pub const R_PARISC_SECREL32: u32 = 41; -/// No relocation, set segment base. -pub const R_PARISC_SEGBASE: u32 = 48; -/// 32 bits segment rel. address. -pub const R_PARISC_SEGREL32: u32 = 49; -/// PLT rel. address, left 21 bits. -pub const R_PARISC_PLTOFF21L: u32 = 50; -/// PLT rel. address, right 14 bits. -pub const R_PARISC_PLTOFF14R: u32 = 54; -/// 32 bits LT-rel. function pointer. -pub const R_PARISC_LTOFF_FPTR32: u32 = 57; -/// LT-rel. fct ptr, left 21 bits. -pub const R_PARISC_LTOFF_FPTR21L: u32 = 58; -/// LT-rel. fct ptr, right 14 bits. -pub const R_PARISC_LTOFF_FPTR14R: u32 = 62; -/// 64 bits function address. -pub const R_PARISC_FPTR64: u32 = 64; -/// 32 bits function address. -pub const R_PARISC_PLABEL32: u32 = 65; -/// Left 21 bits of fdesc address. -pub const R_PARISC_PLABEL21L: u32 = 66; -/// Right 14 bits of fdesc address. -pub const R_PARISC_PLABEL14R: u32 = 70; -/// 64 bits PC-rel. address. -pub const R_PARISC_PCREL64: u32 = 72; -/// 22 bits PC-rel. address. -pub const R_PARISC_PCREL22F: u32 = 74; -/// PC-rel. address, right 14 bits. -pub const R_PARISC_PCREL14WR: u32 = 75; -/// PC rel. address, right 14 bits. -pub const R_PARISC_PCREL14DR: u32 = 76; -/// 16 bits PC-rel. address. -pub const R_PARISC_PCREL16F: u32 = 77; -/// 16 bits PC-rel. address. -pub const R_PARISC_PCREL16WF: u32 = 78; -/// 16 bits PC-rel. address. -pub const R_PARISC_PCREL16DF: u32 = 79; -/// 64 bits of eff. address. -pub const R_PARISC_DIR64: u32 = 80; -/// 14 bits of eff. address. -pub const R_PARISC_DIR14WR: u32 = 83; -/// 14 bits of eff. address. -pub const R_PARISC_DIR14DR: u32 = 84; -/// 16 bits of eff. address. -pub const R_PARISC_DIR16F: u32 = 85; -/// 16 bits of eff. address. -pub const R_PARISC_DIR16WF: u32 = 86; -/// 16 bits of eff. address. -pub const R_PARISC_DIR16DF: u32 = 87; -/// 64 bits of GP-rel. address. -pub const R_PARISC_GPREL64: u32 = 88; -/// GP-rel. address, right 14 bits. -pub const R_PARISC_GPREL14WR: u32 = 91; -/// GP-rel. address, right 14 bits. -pub const R_PARISC_GPREL14DR: u32 = 92; -/// 16 bits GP-rel. address. -pub const R_PARISC_GPREL16F: u32 = 93; -/// 16 bits GP-rel. address. -pub const R_PARISC_GPREL16WF: u32 = 94; -/// 16 bits GP-rel. address. -pub const R_PARISC_GPREL16DF: u32 = 95; -/// 64 bits LT-rel. address. -pub const R_PARISC_LTOFF64: u32 = 96; -/// LT-rel. address, right 14 bits. -pub const R_PARISC_LTOFF14WR: u32 = 99; -/// LT-rel. address, right 14 bits. -pub const R_PARISC_LTOFF14DR: u32 = 100; -/// 16 bits LT-rel. address. -pub const R_PARISC_LTOFF16F: u32 = 101; -/// 16 bits LT-rel. address. -pub const R_PARISC_LTOFF16WF: u32 = 102; -/// 16 bits LT-rel. address. -pub const R_PARISC_LTOFF16DF: u32 = 103; -/// 64 bits section rel. address. -pub const R_PARISC_SECREL64: u32 = 104; -/// 64 bits segment rel. address. -pub const R_PARISC_SEGREL64: u32 = 112; -/// PLT-rel. address, right 14 bits. -pub const R_PARISC_PLTOFF14WR: u32 = 115; -/// PLT-rel. address, right 14 bits. -pub const R_PARISC_PLTOFF14DR: u32 = 116; -/// 16 bits LT-rel. address. -pub const R_PARISC_PLTOFF16F: u32 = 117; -/// 16 bits PLT-rel. address. -pub const R_PARISC_PLTOFF16WF: u32 = 118; -/// 16 bits PLT-rel. address. -pub const R_PARISC_PLTOFF16DF: u32 = 119; -/// 64 bits LT-rel. function ptr. -pub const R_PARISC_LTOFF_FPTR64: u32 = 120; -/// LT-rel. fct. ptr., right 14 bits. -pub const R_PARISC_LTOFF_FPTR14WR: u32 = 123; -/// LT-rel. fct. ptr., right 14 bits. -pub const R_PARISC_LTOFF_FPTR14DR: u32 = 124; -/// 16 bits LT-rel. function ptr. -pub const R_PARISC_LTOFF_FPTR16F: u32 = 125; -/// 16 bits LT-rel. function ptr. -pub const R_PARISC_LTOFF_FPTR16WF: u32 = 126; -/// 16 bits LT-rel. function ptr. -pub const R_PARISC_LTOFF_FPTR16DF: u32 = 127; -pub const R_PARISC_LORESERVE: u32 = 128; -/// Copy relocation. -pub const R_PARISC_COPY: u32 = 128; -/// Dynamic reloc, imported PLT -pub const R_PARISC_IPLT: u32 = 129; -/// Dynamic reloc, exported PLT -pub const R_PARISC_EPLT: u32 = 130; -/// 32 bits TP-rel. address. -pub const R_PARISC_TPREL32: u32 = 153; -/// TP-rel. address, left 21 bits. -pub const R_PARISC_TPREL21L: u32 = 154; -/// TP-rel. address, right 14 bits. -pub const R_PARISC_TPREL14R: u32 = 158; -/// LT-TP-rel. address, left 21 bits. -pub const R_PARISC_LTOFF_TP21L: u32 = 162; -/// LT-TP-rel. address, right 14 bits. -pub const R_PARISC_LTOFF_TP14R: u32 = 166; -/// 14 bits LT-TP-rel. address. -pub const R_PARISC_LTOFF_TP14F: u32 = 167; -/// 64 bits TP-rel. address. -pub const R_PARISC_TPREL64: u32 = 216; -/// TP-rel. address, right 14 bits. -pub const R_PARISC_TPREL14WR: u32 = 219; -/// TP-rel. address, right 14 bits. -pub const R_PARISC_TPREL14DR: u32 = 220; -/// 16 bits TP-rel. address. -pub const R_PARISC_TPREL16F: u32 = 221; -/// 16 bits TP-rel. address. -pub const R_PARISC_TPREL16WF: u32 = 222; -/// 16 bits TP-rel. address. -pub const R_PARISC_TPREL16DF: u32 = 223; -/// 64 bits LT-TP-rel. address. -pub const R_PARISC_LTOFF_TP64: u32 = 224; -/// LT-TP-rel. address, right 14 bits. -pub const R_PARISC_LTOFF_TP14WR: u32 = 227; -/// LT-TP-rel. address, right 14 bits. -pub const R_PARISC_LTOFF_TP14DR: u32 = 228; -/// 16 bits LT-TP-rel. address. -pub const R_PARISC_LTOFF_TP16F: u32 = 229; -/// 16 bits LT-TP-rel. address. -pub const R_PARISC_LTOFF_TP16WF: u32 = 230; -/// 16 bits LT-TP-rel. address. -pub const R_PARISC_LTOFF_TP16DF: u32 = 231; -pub const R_PARISC_GNU_VTENTRY: u32 = 232; -pub const R_PARISC_GNU_VTINHERIT: u32 = 233; -/// GD 21-bit left. -pub const R_PARISC_TLS_GD21L: u32 = 234; -/// GD 14-bit right. -pub const R_PARISC_TLS_GD14R: u32 = 235; -/// GD call to __t_g_a. -pub const R_PARISC_TLS_GDCALL: u32 = 236; -/// LD module 21-bit left. -pub const R_PARISC_TLS_LDM21L: u32 = 237; -/// LD module 14-bit right. -pub const R_PARISC_TLS_LDM14R: u32 = 238; -/// LD module call to __t_g_a. -pub const R_PARISC_TLS_LDMCALL: u32 = 239; -/// LD offset 21-bit left. -pub const R_PARISC_TLS_LDO21L: u32 = 240; -/// LD offset 14-bit right. -pub const R_PARISC_TLS_LDO14R: u32 = 241; -/// DTP module 32-bit. -pub const R_PARISC_TLS_DTPMOD32: u32 = 242; -/// DTP module 64-bit. -pub const R_PARISC_TLS_DTPMOD64: u32 = 243; -/// DTP offset 32-bit. -pub const R_PARISC_TLS_DTPOFF32: u32 = 244; -/// DTP offset 32-bit. -pub const R_PARISC_TLS_DTPOFF64: u32 = 245; -pub const R_PARISC_TLS_LE21L: u32 = R_PARISC_TPREL21L; -pub const R_PARISC_TLS_LE14R: u32 = R_PARISC_TPREL14R; -pub const R_PARISC_TLS_IE21L: u32 = R_PARISC_LTOFF_TP21L; -pub const R_PARISC_TLS_IE14R: u32 = R_PARISC_LTOFF_TP14R; -pub const R_PARISC_TLS_TPREL32: u32 = R_PARISC_TPREL32; -pub const R_PARISC_TLS_TPREL64: u32 = R_PARISC_TPREL64; -pub const R_PARISC_HIRESERVE: u32 = 255; - -// PA-RISC values for `ProgramHeader*::p_type`. - -pub const PT_HP_TLS: u32 = PT_LOOS + 0x0; -pub const PT_HP_CORE_NONE: u32 = PT_LOOS + 0x1; -pub const PT_HP_CORE_VERSION: u32 = PT_LOOS + 0x2; -pub const PT_HP_CORE_KERNEL: u32 = PT_LOOS + 0x3; -pub const PT_HP_CORE_COMM: u32 = PT_LOOS + 0x4; -pub const PT_HP_CORE_PROC: u32 = PT_LOOS + 0x5; -pub const PT_HP_CORE_LOADABLE: u32 = PT_LOOS + 0x6; -pub const PT_HP_CORE_STACK: u32 = PT_LOOS + 0x7; -pub const PT_HP_CORE_SHM: u32 = PT_LOOS + 0x8; -pub const PT_HP_CORE_MMF: u32 = PT_LOOS + 0x9; -pub const PT_HP_PARALLEL: u32 = PT_LOOS + 0x10; -pub const PT_HP_FASTBIND: u32 = PT_LOOS + 0x11; -pub const PT_HP_OPT_ANNOT: u32 = PT_LOOS + 0x12; -pub const PT_HP_HSL_ANNOT: u32 = PT_LOOS + 0x13; -pub const PT_HP_STACK: u32 = PT_LOOS + 0x14; - -pub const PT_PARISC_ARCHEXT: u32 = 0x7000_0000; -pub const PT_PARISC_UNWIND: u32 = 0x7000_0001; - -// PA-RISC values for `ProgramHeader*::p_flags`. - -pub const PF_PARISC_SBP: u32 = 0x0800_0000; - -pub const PF_HP_PAGE_SIZE: u32 = 0x0010_0000; -pub const PF_HP_FAR_SHARED: u32 = 0x0020_0000; -pub const PF_HP_NEAR_SHARED: u32 = 0x0040_0000; -pub const PF_HP_CODE: u32 = 0x0100_0000; -pub const PF_HP_MODIFY: u32 = 0x0200_0000; -pub const PF_HP_LAZYSWAP: u32 = 0x0400_0000; -pub const PF_HP_SBP: u32 = 0x0800_0000; - -// Alpha specific definitions. - -// Alpha values for `FileHeader64::e_flags`. - -/// All addresses must be < 2GB. -pub const EF_ALPHA_32BIT: u32 = 1; -/// Relocations for relaxing exist. -pub const EF_ALPHA_CANRELAX: u32 = 2; - -// Alpha values for `SectionHeader64::sh_type`. - -// These two are primerily concerned with ECOFF debugging info. -pub const SHT_ALPHA_DEBUG: u32 = 0x7000_0001; -pub const SHT_ALPHA_REGINFO: u32 = 0x7000_0002; - -// Alpha values for `SectionHeader64::sh_flags`. - -pub const SHF_ALPHA_GPREL: u32 = 0x1000_0000; - -// Alpha values for `Sym64::st_other`. -/// No PV required. -pub const STO_ALPHA_NOPV: u8 = 0x80; -/// PV only used for initial ldgp. -pub const STO_ALPHA_STD_GPLOAD: u8 = 0x88; - -// Alpha values for `Rel64::r_type`. - -/// No reloc -pub const R_ALPHA_NONE: u32 = 0; -/// Direct 32 bit -pub const R_ALPHA_REFLONG: u32 = 1; -/// Direct 64 bit -pub const R_ALPHA_REFQUAD: u32 = 2; -/// GP relative 32 bit -pub const R_ALPHA_GPREL32: u32 = 3; -/// GP relative 16 bit w/optimization -pub const R_ALPHA_LITERAL: u32 = 4; -/// Optimization hint for LITERAL -pub const R_ALPHA_LITUSE: u32 = 5; -/// Add displacement to GP -pub const R_ALPHA_GPDISP: u32 = 6; -/// PC+4 relative 23 bit shifted -pub const R_ALPHA_BRADDR: u32 = 7; -/// PC+4 relative 16 bit shifted -pub const R_ALPHA_HINT: u32 = 8; -/// PC relative 16 bit -pub const R_ALPHA_SREL16: u32 = 9; -/// PC relative 32 bit -pub const R_ALPHA_SREL32: u32 = 10; -/// PC relative 64 bit -pub const R_ALPHA_SREL64: u32 = 11; -/// GP relative 32 bit, high 16 bits -pub const R_ALPHA_GPRELHIGH: u32 = 17; -/// GP relative 32 bit, low 16 bits -pub const R_ALPHA_GPRELLOW: u32 = 18; -/// GP relative 16 bit -pub const R_ALPHA_GPREL16: u32 = 19; -/// Copy symbol at runtime -pub const R_ALPHA_COPY: u32 = 24; -/// Create GOT entry -pub const R_ALPHA_GLOB_DAT: u32 = 25; -/// Create PLT entry -pub const R_ALPHA_JMP_SLOT: u32 = 26; -/// Adjust by program base -pub const R_ALPHA_RELATIVE: u32 = 27; -pub const R_ALPHA_TLS_GD_HI: u32 = 28; -pub const R_ALPHA_TLSGD: u32 = 29; -pub const R_ALPHA_TLS_LDM: u32 = 30; -pub const R_ALPHA_DTPMOD64: u32 = 31; -pub const R_ALPHA_GOTDTPREL: u32 = 32; -pub const R_ALPHA_DTPREL64: u32 = 33; -pub const R_ALPHA_DTPRELHI: u32 = 34; -pub const R_ALPHA_DTPRELLO: u32 = 35; -pub const R_ALPHA_DTPREL16: u32 = 36; -pub const R_ALPHA_GOTTPREL: u32 = 37; -pub const R_ALPHA_TPREL64: u32 = 38; -pub const R_ALPHA_TPRELHI: u32 = 39; -pub const R_ALPHA_TPRELLO: u32 = 40; -pub const R_ALPHA_TPREL16: u32 = 41; - -// Magic values of the `R_ALPHA_LITUSE` relocation addend. -pub const LITUSE_ALPHA_ADDR: u32 = 0; -pub const LITUSE_ALPHA_BASE: u32 = 1; -pub const LITUSE_ALPHA_BYTOFF: u32 = 2; -pub const LITUSE_ALPHA_JSR: u32 = 3; -pub const LITUSE_ALPHA_TLS_GD: u32 = 4; -pub const LITUSE_ALPHA_TLS_LDM: u32 = 5; - -// Alpha values for `Dyn64::d_tag`. -pub const DT_ALPHA_PLTRO: u32 = DT_LOPROC + 0; - -// PowerPC specific declarations. - -// PowerPC values for `FileHeader*::e_flags`. -/// PowerPC embedded flag -pub const EF_PPC_EMB: u32 = 0x8000_0000; - -// Cygnus local bits below . -/// PowerPC -mrelocatable flag -pub const EF_PPC_RELOCATABLE: u32 = 0x0001_0000; -/// PowerPC -mrelocatable-lib flag -pub const EF_PPC_RELOCATABLE_LIB: u32 = 0x0000_8000; - -// PowerPC values for `Rel*::r_type` defined by the ABIs. -pub const R_PPC_NONE: u32 = 0; -/// 32bit absolute address -pub const R_PPC_ADDR32: u32 = 1; -/// 26bit address, 2 bits ignored. -pub const R_PPC_ADDR24: u32 = 2; -/// 16bit absolute address -pub const R_PPC_ADDR16: u32 = 3; -/// lower 16bit of absolute address -pub const R_PPC_ADDR16_LO: u32 = 4; -/// high 16bit of absolute address -pub const R_PPC_ADDR16_HI: u32 = 5; -/// adjusted high 16bit -pub const R_PPC_ADDR16_HA: u32 = 6; -/// 16bit address, 2 bits ignored -pub const R_PPC_ADDR14: u32 = 7; -pub const R_PPC_ADDR14_BRTAKEN: u32 = 8; -pub const R_PPC_ADDR14_BRNTAKEN: u32 = 9; -/// PC relative 26 bit -pub const R_PPC_REL24: u32 = 10; -/// PC relative 16 bit -pub const R_PPC_REL14: u32 = 11; -pub const R_PPC_REL14_BRTAKEN: u32 = 12; -pub const R_PPC_REL14_BRNTAKEN: u32 = 13; -pub const R_PPC_GOT16: u32 = 14; -pub const R_PPC_GOT16_LO: u32 = 15; -pub const R_PPC_GOT16_HI: u32 = 16; -pub const R_PPC_GOT16_HA: u32 = 17; -pub const R_PPC_PLTREL24: u32 = 18; -pub const R_PPC_COPY: u32 = 19; -pub const R_PPC_GLOB_DAT: u32 = 20; -pub const R_PPC_JMP_SLOT: u32 = 21; -pub const R_PPC_RELATIVE: u32 = 22; -pub const R_PPC_LOCAL24PC: u32 = 23; -pub const R_PPC_UADDR32: u32 = 24; -pub const R_PPC_UADDR16: u32 = 25; -pub const R_PPC_REL32: u32 = 26; -pub const R_PPC_PLT32: u32 = 27; -pub const R_PPC_PLTREL32: u32 = 28; -pub const R_PPC_PLT16_LO: u32 = 29; -pub const R_PPC_PLT16_HI: u32 = 30; -pub const R_PPC_PLT16_HA: u32 = 31; -pub const R_PPC_SDAREL16: u32 = 32; -pub const R_PPC_SECTOFF: u32 = 33; -pub const R_PPC_SECTOFF_LO: u32 = 34; -pub const R_PPC_SECTOFF_HI: u32 = 35; -pub const R_PPC_SECTOFF_HA: u32 = 36; - -// PowerPC values for `Rel*::r_type` defined for the TLS access ABI. -/// none (sym+add)@tls -pub const R_PPC_TLS: u32 = 67; -/// word32 (sym+add)@dtpmod -pub const R_PPC_DTPMOD32: u32 = 68; -/// half16* (sym+add)@tprel -pub const R_PPC_TPREL16: u32 = 69; -/// half16 (sym+add)@tprel@l -pub const R_PPC_TPREL16_LO: u32 = 70; -/// half16 (sym+add)@tprel@h -pub const R_PPC_TPREL16_HI: u32 = 71; -/// half16 (sym+add)@tprel@ha -pub const R_PPC_TPREL16_HA: u32 = 72; -/// word32 (sym+add)@tprel -pub const R_PPC_TPREL32: u32 = 73; -/// half16*(sym+add)@dtprel -pub const R_PPC_DTPREL16: u32 = 74; -/// half16 (sym+add)@dtprel@l -pub const R_PPC_DTPREL16_LO: u32 = 75; -/// half16 (sym+add)@dtprel@h -pub const R_PPC_DTPREL16_HI: u32 = 76; -/// half16 (sym+add)@dtprel@ha -pub const R_PPC_DTPREL16_HA: u32 = 77; -/// word32 (sym+add)@dtprel -pub const R_PPC_DTPREL32: u32 = 78; -/// half16* (sym+add)@got@tlsgd -pub const R_PPC_GOT_TLSGD16: u32 = 79; -/// half16 (sym+add)@got@tlsgd@l -pub const R_PPC_GOT_TLSGD16_LO: u32 = 80; -/// half16 (sym+add)@got@tlsgd@h -pub const R_PPC_GOT_TLSGD16_HI: u32 = 81; -/// half16 (sym+add)@got@tlsgd@ha -pub const R_PPC_GOT_TLSGD16_HA: u32 = 82; -/// half16* (sym+add)@got@tlsld -pub const R_PPC_GOT_TLSLD16: u32 = 83; -/// half16 (sym+add)@got@tlsld@l -pub const R_PPC_GOT_TLSLD16_LO: u32 = 84; -/// half16 (sym+add)@got@tlsld@h -pub const R_PPC_GOT_TLSLD16_HI: u32 = 85; -/// half16 (sym+add)@got@tlsld@ha -pub const R_PPC_GOT_TLSLD16_HA: u32 = 86; -/// half16* (sym+add)@got@tprel -pub const R_PPC_GOT_TPREL16: u32 = 87; -/// half16 (sym+add)@got@tprel@l -pub const R_PPC_GOT_TPREL16_LO: u32 = 88; -/// half16 (sym+add)@got@tprel@h -pub const R_PPC_GOT_TPREL16_HI: u32 = 89; -/// half16 (sym+add)@got@tprel@ha -pub const R_PPC_GOT_TPREL16_HA: u32 = 90; -/// half16* (sym+add)@got@dtprel -pub const R_PPC_GOT_DTPREL16: u32 = 91; -/// half16* (sym+add)@got@dtprel@l -pub const R_PPC_GOT_DTPREL16_LO: u32 = 92; -/// half16* (sym+add)@got@dtprel@h -pub const R_PPC_GOT_DTPREL16_HI: u32 = 93; -/// half16* (sym+add)@got@dtprel@ha -pub const R_PPC_GOT_DTPREL16_HA: u32 = 94; -/// none (sym+add)@tlsgd -pub const R_PPC_TLSGD: u32 = 95; -/// none (sym+add)@tlsld -pub const R_PPC_TLSLD: u32 = 96; - -// PowerPC values for `Rel*::r_type` from the Embedded ELF ABI. -pub const R_PPC_EMB_NADDR32: u32 = 101; -pub const R_PPC_EMB_NADDR16: u32 = 102; -pub const R_PPC_EMB_NADDR16_LO: u32 = 103; -pub const R_PPC_EMB_NADDR16_HI: u32 = 104; -pub const R_PPC_EMB_NADDR16_HA: u32 = 105; -pub const R_PPC_EMB_SDAI16: u32 = 106; -pub const R_PPC_EMB_SDA2I16: u32 = 107; -pub const R_PPC_EMB_SDA2REL: u32 = 108; -/// 16 bit offset in SDA -pub const R_PPC_EMB_SDA21: u32 = 109; -pub const R_PPC_EMB_MRKREF: u32 = 110; -pub const R_PPC_EMB_RELSEC16: u32 = 111; -pub const R_PPC_EMB_RELST_LO: u32 = 112; -pub const R_PPC_EMB_RELST_HI: u32 = 113; -pub const R_PPC_EMB_RELST_HA: u32 = 114; -pub const R_PPC_EMB_BIT_FLD: u32 = 115; -/// 16 bit relative offset in SDA -pub const R_PPC_EMB_RELSDA: u32 = 116; - -// Diab tool values for `Rel*::r_type`. -/// like EMB_SDA21, but lower 16 bit -pub const R_PPC_DIAB_SDA21_LO: u32 = 180; -/// like EMB_SDA21, but high 16 bit -pub const R_PPC_DIAB_SDA21_HI: u32 = 181; -/// like EMB_SDA21, adjusted high 16 -pub const R_PPC_DIAB_SDA21_HA: u32 = 182; -/// like EMB_RELSDA, but lower 16 bit -pub const R_PPC_DIAB_RELSDA_LO: u32 = 183; -/// like EMB_RELSDA, but high 16 bit -pub const R_PPC_DIAB_RELSDA_HI: u32 = 184; -/// like EMB_RELSDA, adjusted high 16 -pub const R_PPC_DIAB_RELSDA_HA: u32 = 185; - -/// GNU extension to support local ifunc. -pub const R_PPC_IRELATIVE: u32 = 248; - -// GNU relocs used in PIC code sequences. -/// half16 (sym+add-.) -pub const R_PPC_REL16: u32 = 249; -/// half16 (sym+add-.)@l -pub const R_PPC_REL16_LO: u32 = 250; -/// half16 (sym+add-.)@h -pub const R_PPC_REL16_HI: u32 = 251; -/// half16 (sym+add-.)@ha -pub const R_PPC_REL16_HA: u32 = 252; - -/// This is a phony reloc to handle any old fashioned TOC16 references that may -/// still be in object files. -pub const R_PPC_TOC16: u32 = 255; - -// PowerPC specific values for `Dyn*::d_tag`. -pub const DT_PPC_GOT: u32 = DT_LOPROC + 0; -pub const DT_PPC_OPT: u32 = DT_LOPROC + 1; - -// PowerPC specific values for the `DT_PPC_OPT` entry. -pub const PPC_OPT_TLS: u32 = 1; - -// PowerPC64 values for `Rel*::r_type` defined by the ABIs. -pub const R_PPC64_NONE: u32 = R_PPC_NONE; -/// 32bit absolute address -pub const R_PPC64_ADDR32: u32 = R_PPC_ADDR32; -/// 26bit address, word aligned -pub const R_PPC64_ADDR24: u32 = R_PPC_ADDR24; -/// 16bit absolute address -pub const R_PPC64_ADDR16: u32 = R_PPC_ADDR16; -/// lower 16bits of address -pub const R_PPC64_ADDR16_LO: u32 = R_PPC_ADDR16_LO; -/// high 16bits of address. -pub const R_PPC64_ADDR16_HI: u32 = R_PPC_ADDR16_HI; -/// adjusted high 16bits. -pub const R_PPC64_ADDR16_HA: u32 = R_PPC_ADDR16_HA; -/// 16bit address, word aligned -pub const R_PPC64_ADDR14: u32 = R_PPC_ADDR14; -pub const R_PPC64_ADDR14_BRTAKEN: u32 = R_PPC_ADDR14_BRTAKEN; -pub const R_PPC64_ADDR14_BRNTAKEN: u32 = R_PPC_ADDR14_BRNTAKEN; -/// PC-rel. 26 bit, word aligned -pub const R_PPC64_REL24: u32 = R_PPC_REL24; -/// PC relative 16 bit -pub const R_PPC64_REL14: u32 = R_PPC_REL14; -pub const R_PPC64_REL14_BRTAKEN: u32 = R_PPC_REL14_BRTAKEN; -pub const R_PPC64_REL14_BRNTAKEN: u32 = R_PPC_REL14_BRNTAKEN; -pub const R_PPC64_GOT16: u32 = R_PPC_GOT16; -pub const R_PPC64_GOT16_LO: u32 = R_PPC_GOT16_LO; -pub const R_PPC64_GOT16_HI: u32 = R_PPC_GOT16_HI; -pub const R_PPC64_GOT16_HA: u32 = R_PPC_GOT16_HA; - -pub const R_PPC64_COPY: u32 = R_PPC_COPY; -pub const R_PPC64_GLOB_DAT: u32 = R_PPC_GLOB_DAT; -pub const R_PPC64_JMP_SLOT: u32 = R_PPC_JMP_SLOT; -pub const R_PPC64_RELATIVE: u32 = R_PPC_RELATIVE; - -pub const R_PPC64_UADDR32: u32 = R_PPC_UADDR32; -pub const R_PPC64_UADDR16: u32 = R_PPC_UADDR16; -pub const R_PPC64_REL32: u32 = R_PPC_REL32; -pub const R_PPC64_PLT32: u32 = R_PPC_PLT32; -pub const R_PPC64_PLTREL32: u32 = R_PPC_PLTREL32; -pub const R_PPC64_PLT16_LO: u32 = R_PPC_PLT16_LO; -pub const R_PPC64_PLT16_HI: u32 = R_PPC_PLT16_HI; -pub const R_PPC64_PLT16_HA: u32 = R_PPC_PLT16_HA; - -pub const R_PPC64_SECTOFF: u32 = R_PPC_SECTOFF; -pub const R_PPC64_SECTOFF_LO: u32 = R_PPC_SECTOFF_LO; -pub const R_PPC64_SECTOFF_HI: u32 = R_PPC_SECTOFF_HI; -pub const R_PPC64_SECTOFF_HA: u32 = R_PPC_SECTOFF_HA; -/// word30 (S + A - P) >> 2 -pub const R_PPC64_ADDR30: u32 = 37; -/// doubleword64 S + A -pub const R_PPC64_ADDR64: u32 = 38; -/// half16 #higher(S + A) -pub const R_PPC64_ADDR16_HIGHER: u32 = 39; -/// half16 #highera(S + A) -pub const R_PPC64_ADDR16_HIGHERA: u32 = 40; -/// half16 #highest(S + A) -pub const R_PPC64_ADDR16_HIGHEST: u32 = 41; -/// half16 #highesta(S + A) -pub const R_PPC64_ADDR16_HIGHESTA: u32 = 42; -/// doubleword64 S + A -pub const R_PPC64_UADDR64: u32 = 43; -/// doubleword64 S + A - P -pub const R_PPC64_REL64: u32 = 44; -/// doubleword64 L + A -pub const R_PPC64_PLT64: u32 = 45; -/// doubleword64 L + A - P -pub const R_PPC64_PLTREL64: u32 = 46; -/// half16* S + A - .TOC -pub const R_PPC64_TOC16: u32 = 47; -/// half16 #lo(S + A - .TOC.) -pub const R_PPC64_TOC16_LO: u32 = 48; -/// half16 #hi(S + A - .TOC.) -pub const R_PPC64_TOC16_HI: u32 = 49; -/// half16 #ha(S + A - .TOC.) -pub const R_PPC64_TOC16_HA: u32 = 50; -/// doubleword64 .TOC -pub const R_PPC64_TOC: u32 = 51; -/// half16* M + A -pub const R_PPC64_PLTGOT16: u32 = 52; -/// half16 #lo(M + A) -pub const R_PPC64_PLTGOT16_LO: u32 = 53; -/// half16 #hi(M + A) -pub const R_PPC64_PLTGOT16_HI: u32 = 54; -/// half16 #ha(M + A) -pub const R_PPC64_PLTGOT16_HA: u32 = 55; - -/// half16ds* (S + A) >> 2 -pub const R_PPC64_ADDR16_DS: u32 = 56; -/// half16ds #lo(S + A) >> 2 -pub const R_PPC64_ADDR16_LO_DS: u32 = 57; -/// half16ds* (G + A) >> 2 -pub const R_PPC64_GOT16_DS: u32 = 58; -/// half16ds #lo(G + A) >> 2 -pub const R_PPC64_GOT16_LO_DS: u32 = 59; -/// half16ds #lo(L + A) >> 2 -pub const R_PPC64_PLT16_LO_DS: u32 = 60; -/// half16ds* (R + A) >> 2 -pub const R_PPC64_SECTOFF_DS: u32 = 61; -/// half16ds #lo(R + A) >> 2 -pub const R_PPC64_SECTOFF_LO_DS: u32 = 62; -/// half16ds* (S + A - .TOC.) >> 2 -pub const R_PPC64_TOC16_DS: u32 = 63; -/// half16ds #lo(S + A - .TOC.) >> 2 -pub const R_PPC64_TOC16_LO_DS: u32 = 64; -/// half16ds* (M + A) >> 2 -pub const R_PPC64_PLTGOT16_DS: u32 = 65; -/// half16ds #lo(M + A) >> 2 -pub const R_PPC64_PLTGOT16_LO_DS: u32 = 66; - -// PowerPC64 values for `Rel*::r_type` defined for the TLS access ABI. -/// none (sym+add)@tls -pub const R_PPC64_TLS: u32 = 67; -/// doubleword64 (sym+add)@dtpmod -pub const R_PPC64_DTPMOD64: u32 = 68; -/// half16* (sym+add)@tprel -pub const R_PPC64_TPREL16: u32 = 69; -/// half16 (sym+add)@tprel@l -pub const R_PPC64_TPREL16_LO: u32 = 70; -/// half16 (sym+add)@tprel@h -pub const R_PPC64_TPREL16_HI: u32 = 71; -/// half16 (sym+add)@tprel@ha -pub const R_PPC64_TPREL16_HA: u32 = 72; -/// doubleword64 (sym+add)@tprel -pub const R_PPC64_TPREL64: u32 = 73; -/// half16* (sym+add)@dtprel -pub const R_PPC64_DTPREL16: u32 = 74; -/// half16 (sym+add)@dtprel@l -pub const R_PPC64_DTPREL16_LO: u32 = 75; -/// half16 (sym+add)@dtprel@h -pub const R_PPC64_DTPREL16_HI: u32 = 76; -/// half16 (sym+add)@dtprel@ha -pub const R_PPC64_DTPREL16_HA: u32 = 77; -/// doubleword64 (sym+add)@dtprel -pub const R_PPC64_DTPREL64: u32 = 78; -/// half16* (sym+add)@got@tlsgd -pub const R_PPC64_GOT_TLSGD16: u32 = 79; -/// half16 (sym+add)@got@tlsgd@l -pub const R_PPC64_GOT_TLSGD16_LO: u32 = 80; -/// half16 (sym+add)@got@tlsgd@h -pub const R_PPC64_GOT_TLSGD16_HI: u32 = 81; -/// half16 (sym+add)@got@tlsgd@ha -pub const R_PPC64_GOT_TLSGD16_HA: u32 = 82; -/// half16* (sym+add)@got@tlsld -pub const R_PPC64_GOT_TLSLD16: u32 = 83; -/// half16 (sym+add)@got@tlsld@l -pub const R_PPC64_GOT_TLSLD16_LO: u32 = 84; -/// half16 (sym+add)@got@tlsld@h -pub const R_PPC64_GOT_TLSLD16_HI: u32 = 85; -/// half16 (sym+add)@got@tlsld@ha -pub const R_PPC64_GOT_TLSLD16_HA: u32 = 86; -/// half16ds* (sym+add)@got@tprel -pub const R_PPC64_GOT_TPREL16_DS: u32 = 87; -/// half16ds (sym+add)@got@tprel@l -pub const R_PPC64_GOT_TPREL16_LO_DS: u32 = 88; -/// half16 (sym+add)@got@tprel@h -pub const R_PPC64_GOT_TPREL16_HI: u32 = 89; -/// half16 (sym+add)@got@tprel@ha -pub const R_PPC64_GOT_TPREL16_HA: u32 = 90; -/// half16ds* (sym+add)@got@dtprel -pub const R_PPC64_GOT_DTPREL16_DS: u32 = 91; -/// half16ds (sym+add)@got@dtprel@l -pub const R_PPC64_GOT_DTPREL16_LO_DS: u32 = 92; -/// half16 (sym+add)@got@dtprel@h -pub const R_PPC64_GOT_DTPREL16_HI: u32 = 93; -/// half16 (sym+add)@got@dtprel@ha -pub const R_PPC64_GOT_DTPREL16_HA: u32 = 94; -/// half16ds* (sym+add)@tprel -pub const R_PPC64_TPREL16_DS: u32 = 95; -/// half16ds (sym+add)@tprel@l -pub const R_PPC64_TPREL16_LO_DS: u32 = 96; -/// half16 (sym+add)@tprel@higher -pub const R_PPC64_TPREL16_HIGHER: u32 = 97; -/// half16 (sym+add)@tprel@highera -pub const R_PPC64_TPREL16_HIGHERA: u32 = 98; -/// half16 (sym+add)@tprel@highest -pub const R_PPC64_TPREL16_HIGHEST: u32 = 99; -/// half16 (sym+add)@tprel@highesta -pub const R_PPC64_TPREL16_HIGHESTA: u32 = 100; -/// half16ds* (sym+add)@dtprel -pub const R_PPC64_DTPREL16_DS: u32 = 101; -/// half16ds (sym+add)@dtprel@l -pub const R_PPC64_DTPREL16_LO_DS: u32 = 102; -/// half16 (sym+add)@dtprel@higher -pub const R_PPC64_DTPREL16_HIGHER: u32 = 103; -/// half16 (sym+add)@dtprel@highera -pub const R_PPC64_DTPREL16_HIGHERA: u32 = 104; -/// half16 (sym+add)@dtprel@highest -pub const R_PPC64_DTPREL16_HIGHEST: u32 = 105; -/// half16 (sym+add)@dtprel@highesta -pub const R_PPC64_DTPREL16_HIGHESTA: u32 = 106; -/// none (sym+add)@tlsgd -pub const R_PPC64_TLSGD: u32 = 107; -/// none (sym+add)@tlsld -pub const R_PPC64_TLSLD: u32 = 108; -/// none -pub const R_PPC64_TOCSAVE: u32 = 109; - -// Added when HA and HI relocs were changed to report overflows. -pub const R_PPC64_ADDR16_HIGH: u32 = 110; -pub const R_PPC64_ADDR16_HIGHA: u32 = 111; -pub const R_PPC64_TPREL16_HIGH: u32 = 112; -pub const R_PPC64_TPREL16_HIGHA: u32 = 113; -pub const R_PPC64_DTPREL16_HIGH: u32 = 114; -pub const R_PPC64_DTPREL16_HIGHA: u32 = 115; - -/// GNU extension to support local ifunc. -pub const R_PPC64_JMP_IREL: u32 = 247; -/// GNU extension to support local ifunc. -pub const R_PPC64_IRELATIVE: u32 = 248; -/// half16 (sym+add-.) -pub const R_PPC64_REL16: u32 = 249; -/// half16 (sym+add-.)@l -pub const R_PPC64_REL16_LO: u32 = 250; -/// half16 (sym+add-.)@h -pub const R_PPC64_REL16_HI: u32 = 251; -/// half16 (sym+add-.)@ha -pub const R_PPC64_REL16_HA: u32 = 252; - -// PowerPC64 values for `FileHeader64::e_flags. -/// PowerPC64 bits specifying ABI. -/// -/// 1 for original function descriptor using ABI, -/// 2 for revised ABI without function descriptors, -/// 0 for unspecified or not using any features affected by the differences. -pub const EF_PPC64_ABI: u32 = 3; - -// PowerPC64 values for `Dyn64::d_tag. -pub const DT_PPC64_GLINK: u32 = DT_LOPROC + 0; -pub const DT_PPC64_OPD: u32 = DT_LOPROC + 1; -pub const DT_PPC64_OPDSZ: u32 = DT_LOPROC + 2; -pub const DT_PPC64_OPT: u32 = DT_LOPROC + 3; - -// PowerPC64 bits for `DT_PPC64_OPT` entry. -pub const PPC64_OPT_TLS: u32 = 1; -pub const PPC64_OPT_MULTI_TOC: u32 = 2; -pub const PPC64_OPT_LOCALENTRY: u32 = 4; - -// PowerPC64 values for `Sym64::st_other. -pub const STO_PPC64_LOCAL_BIT: u8 = 5; -pub const STO_PPC64_LOCAL_MASK: u8 = 7 << STO_PPC64_LOCAL_BIT; - -// ARM specific declarations. - -// ARM values for `FileHeader*::e_flags`. -pub const EF_ARM_RELEXEC: u32 = 0x01; -pub const EF_ARM_HASENTRY: u32 = 0x02; -pub const EF_ARM_INTERWORK: u32 = 0x04; -pub const EF_ARM_APCS_26: u32 = 0x08; -pub const EF_ARM_APCS_FLOAT: u32 = 0x10; -pub const EF_ARM_PIC: u32 = 0x20; -/// 8-bit structure alignment is in use -pub const EF_ARM_ALIGN8: u32 = 0x40; -pub const EF_ARM_NEW_ABI: u32 = 0x80; -pub const EF_ARM_OLD_ABI: u32 = 0x100; -pub const EF_ARM_SOFT_FLOAT: u32 = 0x200; -pub const EF_ARM_VFP_FLOAT: u32 = 0x400; -pub const EF_ARM_MAVERICK_FLOAT: u32 = 0x800; - -/// NB conflicts with EF_ARM_SOFT_FLOAT -pub const EF_ARM_ABI_FLOAT_SOFT: u32 = 0x200; -/// NB conflicts with EF_ARM_VFP_FLOAT -pub const EF_ARM_ABI_FLOAT_HARD: u32 = 0x400; - -// Other constants defined in the ARM ELF spec. version B-01. -// NB. These conflict with values defined above. -pub const EF_ARM_SYMSARESORTED: u32 = 0x04; -pub const EF_ARM_DYNSYMSUSESEGIDX: u32 = 0x08; -pub const EF_ARM_MAPSYMSFIRST: u32 = 0x10; - -// Constants defined in AAELF. -pub const EF_ARM_BE8: u32 = 0x0080_0000; -pub const EF_ARM_LE8: u32 = 0x0040_0000; - -pub const EF_ARM_EABIMASK: u32 = 0xff00_0000; -pub const EF_ARM_EABI_UNKNOWN: u32 = 0x0000_0000; -pub const EF_ARM_EABI_VER1: u32 = 0x0100_0000; -pub const EF_ARM_EABI_VER2: u32 = 0x0200_0000; -pub const EF_ARM_EABI_VER3: u32 = 0x0300_0000; -pub const EF_ARM_EABI_VER4: u32 = 0x0400_0000; -pub const EF_ARM_EABI_VER5: u32 = 0x0500_0000; - -// ARM Thumb values for `st_type` component of `Sym*::st_info`. -/// A Thumb function. -pub const STT_ARM_TFUNC: u8 = STT_LOPROC; -/// A Thumb label. -pub const STT_ARM_16BIT: u8 = STT_HIPROC; - -// ARM values for `SectionHeader*::sh_flags`. -/// Section contains an entry point -pub const SHF_ARM_ENTRYSECT: u32 = 0x1000_0000; -/// Section may be multiply defined in the input to a link step. -pub const SHF_ARM_COMDEF: u32 = 0x8000_0000; - -// ARM values for `ProgramHeader*::p_flags`. -/// Segment contains the location addressed by the static base. -pub const PF_ARM_SB: u32 = 0x1000_0000; -/// Position-independent segment. -pub const PF_ARM_PI: u32 = 0x2000_0000; -/// Absolute segment. -pub const PF_ARM_ABS: u32 = 0x4000_0000; - -// ARM values for `ProgramHeader*::p_type`. -/// ARM unwind segment. -pub const PT_ARM_EXIDX: u32 = PT_LOPROC + 1; - -// ARM values for `SectionHeader*::sh_type`. -/// ARM unwind section. -pub const SHT_ARM_EXIDX: u32 = SHT_LOPROC + 1; -/// Preemption details. -pub const SHT_ARM_PREEMPTMAP: u32 = SHT_LOPROC + 2; -/// ARM attributes section. -pub const SHT_ARM_ATTRIBUTES: u32 = SHT_LOPROC + 3; - -// AArch64 values for `Rel*::r_type`. - -/// No relocation. -pub const R_AARCH64_NONE: u32 = 0; - -// ILP32 AArch64 relocs. -/// Direct 32 bit. -pub const R_AARCH64_P32_ABS32: u32 = 1; -/// Copy symbol at runtime. -pub const R_AARCH64_P32_COPY: u32 = 180; -/// Create GOT entry. -pub const R_AARCH64_P32_GLOB_DAT: u32 = 181; -/// Create PLT entry. -pub const R_AARCH64_P32_JUMP_SLOT: u32 = 182; -/// Adjust by program base. -pub const R_AARCH64_P32_RELATIVE: u32 = 183; -/// Module number, 32 bit. -pub const R_AARCH64_P32_TLS_DTPMOD: u32 = 184; -/// Module-relative offset, 32 bit. -pub const R_AARCH64_P32_TLS_DTPREL: u32 = 185; -/// TP-relative offset, 32 bit. -pub const R_AARCH64_P32_TLS_TPREL: u32 = 186; -/// TLS Descriptor. -pub const R_AARCH64_P32_TLSDESC: u32 = 187; -/// STT_GNU_IFUNC relocation. -pub const R_AARCH64_P32_IRELATIVE: u32 = 188; - -// LP64 AArch64 relocs. -/// Direct 64 bit. -pub const R_AARCH64_ABS64: u32 = 257; -/// Direct 32 bit. -pub const R_AARCH64_ABS32: u32 = 258; -/// Direct 16-bit. -pub const R_AARCH64_ABS16: u32 = 259; -/// PC-relative 64-bit. -pub const R_AARCH64_PREL64: u32 = 260; -/// PC-relative 32-bit. -pub const R_AARCH64_PREL32: u32 = 261; -/// PC-relative 16-bit. -pub const R_AARCH64_PREL16: u32 = 262; -/// Dir. MOVZ imm. from bits 15:0. -pub const R_AARCH64_MOVW_UABS_G0: u32 = 263; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_UABS_G0_NC: u32 = 264; -/// Dir. MOVZ imm. from bits 31:16. -pub const R_AARCH64_MOVW_UABS_G1: u32 = 265; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_UABS_G1_NC: u32 = 266; -/// Dir. MOVZ imm. from bits 47:32. -pub const R_AARCH64_MOVW_UABS_G2: u32 = 267; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_UABS_G2_NC: u32 = 268; -/// Dir. MOV{K,Z} imm. from 63:48. -pub const R_AARCH64_MOVW_UABS_G3: u32 = 269; -/// Dir. MOV{N,Z} imm. from 15:0. -pub const R_AARCH64_MOVW_SABS_G0: u32 = 270; -/// Dir. MOV{N,Z} imm. from 31:16. -pub const R_AARCH64_MOVW_SABS_G1: u32 = 271; -/// Dir. MOV{N,Z} imm. from 47:32. -pub const R_AARCH64_MOVW_SABS_G2: u32 = 272; -/// PC-rel. LD imm. from bits 20:2. -pub const R_AARCH64_LD_PREL_LO19: u32 = 273; -/// PC-rel. ADR imm. from bits 20:0. -pub const R_AARCH64_ADR_PREL_LO21: u32 = 274; -/// Page-rel. ADRP imm. from 32:12. -pub const R_AARCH64_ADR_PREL_PG_HI21: u32 = 275; -/// Likewise; no overflow check. -pub const R_AARCH64_ADR_PREL_PG_HI21_NC: u32 = 276; -/// Dir. ADD imm. from bits 11:0. -pub const R_AARCH64_ADD_ABS_LO12_NC: u32 = 277; -/// Likewise for LD/ST; no check. -pub const R_AARCH64_LDST8_ABS_LO12_NC: u32 = 278; -/// PC-rel. TBZ/TBNZ imm. from 15:2. -pub const R_AARCH64_TSTBR14: u32 = 279; -/// PC-rel. cond. br. imm. from 20:2. -pub const R_AARCH64_CONDBR19: u32 = 280; -/// PC-rel. B imm. from bits 27:2. -pub const R_AARCH64_JUMP26: u32 = 282; -/// Likewise for CALL. -pub const R_AARCH64_CALL26: u32 = 283; -/// Dir. ADD imm. from bits 11:1. -pub const R_AARCH64_LDST16_ABS_LO12_NC: u32 = 284; -/// Likewise for bits 11:2. -pub const R_AARCH64_LDST32_ABS_LO12_NC: u32 = 285; -/// Likewise for bits 11:3. -pub const R_AARCH64_LDST64_ABS_LO12_NC: u32 = 286; -/// PC-rel. MOV{N,Z} imm. from 15:0. -pub const R_AARCH64_MOVW_PREL_G0: u32 = 287; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_PREL_G0_NC: u32 = 288; -/// PC-rel. MOV{N,Z} imm. from 31:16. -pub const R_AARCH64_MOVW_PREL_G1: u32 = 289; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_PREL_G1_NC: u32 = 290; -/// PC-rel. MOV{N,Z} imm. from 47:32. -pub const R_AARCH64_MOVW_PREL_G2: u32 = 291; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_PREL_G2_NC: u32 = 292; -/// PC-rel. MOV{N,Z} imm. from 63:48. -pub const R_AARCH64_MOVW_PREL_G3: u32 = 293; -/// Dir. ADD imm. from bits 11:4. -pub const R_AARCH64_LDST128_ABS_LO12_NC: u32 = 299; -/// GOT-rel. off. MOV{N,Z} imm. 15:0. -pub const R_AARCH64_MOVW_GOTOFF_G0: u32 = 300; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_GOTOFF_G0_NC: u32 = 301; -/// GOT-rel. o. MOV{N,Z} imm. 31:16. -pub const R_AARCH64_MOVW_GOTOFF_G1: u32 = 302; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_GOTOFF_G1_NC: u32 = 303; -/// GOT-rel. o. MOV{N,Z} imm. 47:32. -pub const R_AARCH64_MOVW_GOTOFF_G2: u32 = 304; -/// Likewise for MOVK; no check. -pub const R_AARCH64_MOVW_GOTOFF_G2_NC: u32 = 305; -/// GOT-rel. o. MOV{N,Z} imm. 63:48. -pub const R_AARCH64_MOVW_GOTOFF_G3: u32 = 306; -/// GOT-relative 64-bit. -pub const R_AARCH64_GOTREL64: u32 = 307; -/// GOT-relative 32-bit. -pub const R_AARCH64_GOTREL32: u32 = 308; -/// PC-rel. GOT off. load imm. 20:2. -pub const R_AARCH64_GOT_LD_PREL19: u32 = 309; -/// GOT-rel. off. LD/ST imm. 14:3. -pub const R_AARCH64_LD64_GOTOFF_LO15: u32 = 310; -/// P-page-rel. GOT off. ADRP 32:12. -pub const R_AARCH64_ADR_GOT_PAGE: u32 = 311; -/// Dir. GOT off. LD/ST imm. 11:3. -pub const R_AARCH64_LD64_GOT_LO12_NC: u32 = 312; -/// GOT-page-rel. GOT off. LD/ST 14:3 -pub const R_AARCH64_LD64_GOTPAGE_LO15: u32 = 313; -/// PC-relative ADR imm. 20:0. -pub const R_AARCH64_TLSGD_ADR_PREL21: u32 = 512; -/// page-rel. ADRP imm. 32:12. -pub const R_AARCH64_TLSGD_ADR_PAGE21: u32 = 513; -/// direct ADD imm. from 11:0. -pub const R_AARCH64_TLSGD_ADD_LO12_NC: u32 = 514; -/// GOT-rel. MOV{N,Z} 31:16. -pub const R_AARCH64_TLSGD_MOVW_G1: u32 = 515; -/// GOT-rel. MOVK imm. 15:0. -pub const R_AARCH64_TLSGD_MOVW_G0_NC: u32 = 516; -/// Like 512; local dynamic model. -pub const R_AARCH64_TLSLD_ADR_PREL21: u32 = 517; -/// Like 513; local dynamic model. -pub const R_AARCH64_TLSLD_ADR_PAGE21: u32 = 518; -/// Like 514; local dynamic model. -pub const R_AARCH64_TLSLD_ADD_LO12_NC: u32 = 519; -/// Like 515; local dynamic model. -pub const R_AARCH64_TLSLD_MOVW_G1: u32 = 520; -/// Like 516; local dynamic model. -pub const R_AARCH64_TLSLD_MOVW_G0_NC: u32 = 521; -/// TLS PC-rel. load imm. 20:2. -pub const R_AARCH64_TLSLD_LD_PREL19: u32 = 522; -/// TLS DTP-rel. MOV{N,Z} 47:32. -pub const R_AARCH64_TLSLD_MOVW_DTPREL_G2: u32 = 523; -/// TLS DTP-rel. MOV{N,Z} 31:16. -pub const R_AARCH64_TLSLD_MOVW_DTPREL_G1: u32 = 524; -/// Likewise; MOVK; no check. -pub const R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC: u32 = 525; -/// TLS DTP-rel. MOV{N,Z} 15:0. -pub const R_AARCH64_TLSLD_MOVW_DTPREL_G0: u32 = 526; -/// Likewise; MOVK; no check. -pub const R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC: u32 = 527; -/// DTP-rel. ADD imm. from 23:12. -pub const R_AARCH64_TLSLD_ADD_DTPREL_HI12: u32 = 528; -/// DTP-rel. ADD imm. from 11:0. -pub const R_AARCH64_TLSLD_ADD_DTPREL_LO12: u32 = 529; -/// Likewise; no ovfl. check. -pub const R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC: u32 = 530; -/// DTP-rel. LD/ST imm. 11:0. -pub const R_AARCH64_TLSLD_LDST8_DTPREL_LO12: u32 = 531; -/// Likewise; no check. -pub const R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC: u32 = 532; -/// DTP-rel. LD/ST imm. 11:1. -pub const R_AARCH64_TLSLD_LDST16_DTPREL_LO12: u32 = 533; -/// Likewise; no check. -pub const R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC: u32 = 534; -/// DTP-rel. LD/ST imm. 11:2. -pub const R_AARCH64_TLSLD_LDST32_DTPREL_LO12: u32 = 535; -/// Likewise; no check. -pub const R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC: u32 = 536; -/// DTP-rel. LD/ST imm. 11:3. -pub const R_AARCH64_TLSLD_LDST64_DTPREL_LO12: u32 = 537; -/// Likewise; no check. -pub const R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC: u32 = 538; -/// GOT-rel. MOV{N,Z} 31:16. -pub const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1: u32 = 539; -/// GOT-rel. MOVK 15:0. -pub const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: u32 = 540; -/// Page-rel. ADRP 32:12. -pub const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: u32 = 541; -/// Direct LD off. 11:3. -pub const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: u32 = 542; -/// PC-rel. load imm. 20:2. -pub const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19: u32 = 543; -/// TLS TP-rel. MOV{N,Z} 47:32. -pub const R_AARCH64_TLSLE_MOVW_TPREL_G2: u32 = 544; -/// TLS TP-rel. MOV{N,Z} 31:16. -pub const R_AARCH64_TLSLE_MOVW_TPREL_G1: u32 = 545; -/// Likewise; MOVK; no check. -pub const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: u32 = 546; -/// TLS TP-rel. MOV{N,Z} 15:0. -pub const R_AARCH64_TLSLE_MOVW_TPREL_G0: u32 = 547; -/// Likewise; MOVK; no check. -pub const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: u32 = 548; -/// TP-rel. ADD imm. 23:12. -pub const R_AARCH64_TLSLE_ADD_TPREL_HI12: u32 = 549; -/// TP-rel. ADD imm. 11:0. -pub const R_AARCH64_TLSLE_ADD_TPREL_LO12: u32 = 550; -/// Likewise; no ovfl. check. -pub const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: u32 = 551; -/// TP-rel. LD/ST off. 11:0. -pub const R_AARCH64_TLSLE_LDST8_TPREL_LO12: u32 = 552; -/// Likewise; no ovfl. check. -pub const R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: u32 = 553; -/// TP-rel. LD/ST off. 11:1. -pub const R_AARCH64_TLSLE_LDST16_TPREL_LO12: u32 = 554; -/// Likewise; no check. -pub const R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: u32 = 555; -/// TP-rel. LD/ST off. 11:2. -pub const R_AARCH64_TLSLE_LDST32_TPREL_LO12: u32 = 556; -/// Likewise; no check. -pub const R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: u32 = 557; -/// TP-rel. LD/ST off. 11:3. -pub const R_AARCH64_TLSLE_LDST64_TPREL_LO12: u32 = 558; -/// Likewise; no check. -pub const R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: u32 = 559; -/// PC-rel. load immediate 20:2. -pub const R_AARCH64_TLSDESC_LD_PREL19: u32 = 560; -/// PC-rel. ADR immediate 20:0. -pub const R_AARCH64_TLSDESC_ADR_PREL21: u32 = 561; -/// Page-rel. ADRP imm. 32:12. -pub const R_AARCH64_TLSDESC_ADR_PAGE21: u32 = 562; -/// Direct LD off. from 11:3. -pub const R_AARCH64_TLSDESC_LD64_LO12: u32 = 563; -/// Direct ADD imm. from 11:0. -pub const R_AARCH64_TLSDESC_ADD_LO12: u32 = 564; -/// GOT-rel. MOV{N,Z} imm. 31:16. -pub const R_AARCH64_TLSDESC_OFF_G1: u32 = 565; -/// GOT-rel. MOVK imm. 15:0; no ck. -pub const R_AARCH64_TLSDESC_OFF_G0_NC: u32 = 566; -/// Relax LDR. -pub const R_AARCH64_TLSDESC_LDR: u32 = 567; -/// Relax ADD. -pub const R_AARCH64_TLSDESC_ADD: u32 = 568; -/// Relax BLR. -pub const R_AARCH64_TLSDESC_CALL: u32 = 569; -/// TP-rel. LD/ST off. 11:4. -pub const R_AARCH64_TLSLE_LDST128_TPREL_LO12: u32 = 570; -/// Likewise; no check. -pub const R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: u32 = 571; -/// DTP-rel. LD/ST imm. 11:4. -pub const R_AARCH64_TLSLD_LDST128_DTPREL_LO12: u32 = 572; -/// Likewise; no check. -pub const R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC: u32 = 573; -/// Copy symbol at runtime. -pub const R_AARCH64_COPY: u32 = 1024; -/// Create GOT entry. -pub const R_AARCH64_GLOB_DAT: u32 = 1025; -/// Create PLT entry. -pub const R_AARCH64_JUMP_SLOT: u32 = 1026; -/// Adjust by program base. -pub const R_AARCH64_RELATIVE: u32 = 1027; -/// Module number, 64 bit. -pub const R_AARCH64_TLS_DTPMOD: u32 = 1028; -/// Module-relative offset, 64 bit. -pub const R_AARCH64_TLS_DTPREL: u32 = 1029; -/// TP-relative offset, 64 bit. -pub const R_AARCH64_TLS_TPREL: u32 = 1030; -/// TLS Descriptor. -pub const R_AARCH64_TLSDESC: u32 = 1031; -/// STT_GNU_IFUNC relocation. -pub const R_AARCH64_IRELATIVE: u32 = 1032; - -// AVR values for `FileHeader*::e_flags`. - -/// Bitmask for `EF_AVR_ARCH_*`. -pub const EF_AVR_ARCH: u32 = 0x7F; - -/// If set, it is assumed that the elf file uses local symbols as reference -/// for the relocations so that linker relaxation is possible. -pub const EF_AVR_LINKRELAX_PREPARED: u32 = 0x80; - -pub const EF_AVR_ARCH_AVR1: u32 = 1; -pub const EF_AVR_ARCH_AVR2: u32 = 2; -pub const EF_AVR_ARCH_AVR25: u32 = 25; -pub const EF_AVR_ARCH_AVR3: u32 = 3; -pub const EF_AVR_ARCH_AVR31: u32 = 31; -pub const EF_AVR_ARCH_AVR35: u32 = 35; -pub const EF_AVR_ARCH_AVR4: u32 = 4; -pub const EF_AVR_ARCH_AVR5: u32 = 5; -pub const EF_AVR_ARCH_AVR51: u32 = 51; -pub const EF_AVR_ARCH_AVR6: u32 = 6; -pub const EF_AVR_ARCH_AVRTINY: u32 = 100; -pub const EF_AVR_ARCH_XMEGA1: u32 = 101; -pub const EF_AVR_ARCH_XMEGA2: u32 = 102; -pub const EF_AVR_ARCH_XMEGA3: u32 = 103; -pub const EF_AVR_ARCH_XMEGA4: u32 = 104; -pub const EF_AVR_ARCH_XMEGA5: u32 = 105; -pub const EF_AVR_ARCH_XMEGA6: u32 = 106; -pub const EF_AVR_ARCH_XMEGA7: u32 = 107; - -// AVR values for `Rel*::r_type`. - -pub const R_AVR_NONE: u32 = 0; -/// Direct 32 bit -pub const R_AVR_32: u32 = 1; -pub const R_AVR_7_PCREL: u32 = 2; -pub const R_AVR_13_PCREL: u32 = 3; -/// Direct 16 bit -pub const R_AVR_16: u32 = 4; -pub const R_AVR_16_PM: u32 = 5; -pub const R_AVR_LO8_LDI: u32 = 6; -pub const R_AVR_HI8_LDI: u32 = 7; -pub const R_AVR_HH8_LDI: u32 = 8; -pub const R_AVR_LO8_LDI_NEG: u32 = 9; -pub const R_AVR_HI8_LDI_NEG: u32 = 10; -pub const R_AVR_HH8_LDI_NEG: u32 = 11; -pub const R_AVR_LO8_LDI_PM: u32 = 12; -pub const R_AVR_HI8_LDI_PM: u32 = 13; -pub const R_AVR_HH8_LDI_PM: u32 = 14; -pub const R_AVR_LO8_LDI_PM_NEG: u32 = 15; -pub const R_AVR_HI8_LDI_PM_NEG: u32 = 16; -pub const R_AVR_HH8_LDI_PM_NEG: u32 = 17; -pub const R_AVR_CALL: u32 = 18; -pub const R_AVR_LDI: u32 = 19; -pub const R_AVR_6: u32 = 20; -pub const R_AVR_6_ADIW: u32 = 21; -pub const R_AVR_MS8_LDI: u32 = 22; -pub const R_AVR_MS8_LDI_NEG: u32 = 23; -pub const R_AVR_LO8_LDI_GS: u32 = 24; -pub const R_AVR_HI8_LDI_GS: u32 = 25; -pub const R_AVR_8: u32 = 26; -pub const R_AVR_8_LO8: u32 = 27; -pub const R_AVR_8_HI8: u32 = 28; -pub const R_AVR_8_HLO8: u32 = 29; -pub const R_AVR_DIFF8: u32 = 30; -pub const R_AVR_DIFF16: u32 = 31; -pub const R_AVR_DIFF32: u32 = 32; -pub const R_AVR_LDS_STS_16: u32 = 33; -pub const R_AVR_PORT6: u32 = 34; -pub const R_AVR_PORT5: u32 = 35; -pub const R_AVR_32_PCREL: u32 = 36; - -// MSP430 values for `Rel*::r_type`. - -/// Direct 32 bit -pub const R_MSP430_32: u32 = 1; -/// Direct 16 bit -pub const R_MSP430_16_BYTE: u32 = 5; - -// Hexagon values for `Rel*::r_type`. - -/// Direct 32 bit -pub const R_HEX_32: u32 = 6; - -// ARM values for `Rel*::r_type`. - -/// No reloc -pub const R_ARM_NONE: u32 = 0; -/// Deprecated PC relative 26 bit branch. -pub const R_ARM_PC24: u32 = 1; -/// Direct 32 bit -pub const R_ARM_ABS32: u32 = 2; -/// PC relative 32 bit -pub const R_ARM_REL32: u32 = 3; -pub const R_ARM_PC13: u32 = 4; -/// Direct 16 bit -pub const R_ARM_ABS16: u32 = 5; -/// Direct 12 bit -pub const R_ARM_ABS12: u32 = 6; -/// Direct & 0x7C (`LDR`, `STR`). -pub const R_ARM_THM_ABS5: u32 = 7; -/// Direct 8 bit -pub const R_ARM_ABS8: u32 = 8; -pub const R_ARM_SBREL32: u32 = 9; -/// PC relative 24 bit (Thumb32 `BL`). -pub const R_ARM_THM_PC22: u32 = 10; -/// PC relative & 0x3FC (Thumb16 `LDR`, `ADD`, `ADR`). -pub const R_ARM_THM_PC8: u32 = 11; -pub const R_ARM_AMP_VCALL9: u32 = 12; -/// Obsolete static relocation. -pub const R_ARM_SWI24: u32 = 13; -/// Dynamic relocation. -pub const R_ARM_TLS_DESC: u32 = 13; -/// Reserved. -pub const R_ARM_THM_SWI8: u32 = 14; -/// Reserved. -pub const R_ARM_XPC25: u32 = 15; -/// Reserved. -pub const R_ARM_THM_XPC22: u32 = 16; -/// ID of module containing symbol -pub const R_ARM_TLS_DTPMOD32: u32 = 17; -/// Offset in TLS block -pub const R_ARM_TLS_DTPOFF32: u32 = 18; -/// Offset in static TLS block -pub const R_ARM_TLS_TPOFF32: u32 = 19; -/// Copy symbol at runtime -pub const R_ARM_COPY: u32 = 20; -/// Create GOT entry -pub const R_ARM_GLOB_DAT: u32 = 21; -/// Create PLT entry -pub const R_ARM_JUMP_SLOT: u32 = 22; -/// Adjust by program base -pub const R_ARM_RELATIVE: u32 = 23; -/// 32 bit offset to GOT -pub const R_ARM_GOTOFF: u32 = 24; -/// 32 bit PC relative offset to GOT -pub const R_ARM_GOTPC: u32 = 25; -/// 32 bit GOT entry -pub const R_ARM_GOT32: u32 = 26; -/// Deprecated, 32 bit PLT address. -pub const R_ARM_PLT32: u32 = 27; -/// PC relative 24 bit (`BL`, `BLX`). -pub const R_ARM_CALL: u32 = 28; -/// PC relative 24 bit (`B`, `BL`). -pub const R_ARM_JUMP24: u32 = 29; -/// PC relative 24 bit (Thumb32 `B.W`). -pub const R_ARM_THM_JUMP24: u32 = 30; -/// Adjust by program base. -pub const R_ARM_BASE_ABS: u32 = 31; -/// Obsolete. -pub const R_ARM_ALU_PCREL_7_0: u32 = 32; -/// Obsolete. -pub const R_ARM_ALU_PCREL_15_8: u32 = 33; -/// Obsolete. -pub const R_ARM_ALU_PCREL_23_15: u32 = 34; -/// Deprecated, prog. base relative. -pub const R_ARM_LDR_SBREL_11_0: u32 = 35; -/// Deprecated, prog. base relative. -pub const R_ARM_ALU_SBREL_19_12: u32 = 36; -/// Deprecated, prog. base relative. -pub const R_ARM_ALU_SBREL_27_20: u32 = 37; -pub const R_ARM_TARGET1: u32 = 38; -/// Program base relative. -pub const R_ARM_SBREL31: u32 = 39; -pub const R_ARM_V4BX: u32 = 40; -pub const R_ARM_TARGET2: u32 = 41; -/// 32 bit PC relative. -pub const R_ARM_PREL31: u32 = 42; -/// Direct 16-bit (`MOVW`). -pub const R_ARM_MOVW_ABS_NC: u32 = 43; -/// Direct high 16-bit (`MOVT`). -pub const R_ARM_MOVT_ABS: u32 = 44; -/// PC relative 16-bit (`MOVW`). -pub const R_ARM_MOVW_PREL_NC: u32 = 45; -/// PC relative (MOVT). -pub const R_ARM_MOVT_PREL: u32 = 46; -/// Direct 16 bit (Thumb32 `MOVW`). -pub const R_ARM_THM_MOVW_ABS_NC: u32 = 47; -/// Direct high 16 bit (Thumb32 `MOVT`). -pub const R_ARM_THM_MOVT_ABS: u32 = 48; -/// PC relative 16 bit (Thumb32 `MOVW`). -pub const R_ARM_THM_MOVW_PREL_NC: u32 = 49; -/// PC relative high 16 bit (Thumb32 `MOVT`). -pub const R_ARM_THM_MOVT_PREL: u32 = 50; -/// PC relative 20 bit (Thumb32 `B.W`). -pub const R_ARM_THM_JUMP19: u32 = 51; -/// PC relative X & 0x7E (Thumb16 `CBZ`, `CBNZ`). -pub const R_ARM_THM_JUMP6: u32 = 52; -/// PC relative 12 bit (Thumb32 `ADR.W`). -pub const R_ARM_THM_ALU_PREL_11_0: u32 = 53; -/// PC relative 12 bit (Thumb32 `LDR{D,SB,H,SH}`). -pub const R_ARM_THM_PC12: u32 = 54; -/// Direct 32-bit. -pub const R_ARM_ABS32_NOI: u32 = 55; -/// PC relative 32-bit. -pub const R_ARM_REL32_NOI: u32 = 56; -/// PC relative (`ADD`, `SUB`). -pub const R_ARM_ALU_PC_G0_NC: u32 = 57; -/// PC relative (`ADD`, `SUB`). -pub const R_ARM_ALU_PC_G0: u32 = 58; -/// PC relative (`ADD`, `SUB`). -pub const R_ARM_ALU_PC_G1_NC: u32 = 59; -/// PC relative (`ADD`, `SUB`). -pub const R_ARM_ALU_PC_G1: u32 = 60; -/// PC relative (`ADD`, `SUB`). -pub const R_ARM_ALU_PC_G2: u32 = 61; -/// PC relative (`LDR`,`STR`,`LDRB`,`STRB`). -pub const R_ARM_LDR_PC_G1: u32 = 62; -/// PC relative (`LDR`,`STR`,`LDRB`,`STRB`). -pub const R_ARM_LDR_PC_G2: u32 = 63; -/// PC relative (`STR{D,H}`, `LDR{D,SB,H,SH}`). -pub const R_ARM_LDRS_PC_G0: u32 = 64; -/// PC relative (`STR{D,H}`, `LDR{D,SB,H,SH}`). -pub const R_ARM_LDRS_PC_G1: u32 = 65; -/// PC relative (`STR{D,H}`, `LDR{D,SB,H,SH}`). -pub const R_ARM_LDRS_PC_G2: u32 = 66; -/// PC relative (`LDC`, `STC`). -pub const R_ARM_LDC_PC_G0: u32 = 67; -/// PC relative (`LDC`, `STC`). -pub const R_ARM_LDC_PC_G1: u32 = 68; -/// PC relative (`LDC`, `STC`). -pub const R_ARM_LDC_PC_G2: u32 = 69; -/// Program base relative (`ADD`,`SUB`). -pub const R_ARM_ALU_SB_G0_NC: u32 = 70; -/// Program base relative (`ADD`,`SUB`). -pub const R_ARM_ALU_SB_G0: u32 = 71; -/// Program base relative (`ADD`,`SUB`). -pub const R_ARM_ALU_SB_G1_NC: u32 = 72; -/// Program base relative (`ADD`,`SUB`). -pub const R_ARM_ALU_SB_G1: u32 = 73; -/// Program base relative (`ADD`,`SUB`). -pub const R_ARM_ALU_SB_G2: u32 = 74; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDR_SB_G0: u32 = 75; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDR_SB_G1: u32 = 76; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDR_SB_G2: u32 = 77; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDRS_SB_G0: u32 = 78; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDRS_SB_G1: u32 = 79; -/// Program base relative (`LDR`, `STR`, `LDRB`, `STRB`). -pub const R_ARM_LDRS_SB_G2: u32 = 80; -/// Program base relative (`LDC`,`STC`). -pub const R_ARM_LDC_SB_G0: u32 = 81; -/// Program base relative (`LDC`,`STC`). -pub const R_ARM_LDC_SB_G1: u32 = 82; -/// Program base relative (`LDC`,`STC`). -pub const R_ARM_LDC_SB_G2: u32 = 83; -/// Program base relative 16 bit (`MOVW`). -pub const R_ARM_MOVW_BREL_NC: u32 = 84; -/// Program base relative high 16 bit (`MOVT`). -pub const R_ARM_MOVT_BREL: u32 = 85; -/// Program base relative 16 bit (`MOVW`). -pub const R_ARM_MOVW_BREL: u32 = 86; -/// Program base relative 16 bit (Thumb32 `MOVW`). -pub const R_ARM_THM_MOVW_BREL_NC: u32 = 87; -/// Program base relative high 16 bit (Thumb32 `MOVT`). -pub const R_ARM_THM_MOVT_BREL: u32 = 88; -/// Program base relative 16 bit (Thumb32 `MOVW`). -pub const R_ARM_THM_MOVW_BREL: u32 = 89; -pub const R_ARM_TLS_GOTDESC: u32 = 90; -pub const R_ARM_TLS_CALL: u32 = 91; -/// TLS relaxation. -pub const R_ARM_TLS_DESCSEQ: u32 = 92; -pub const R_ARM_THM_TLS_CALL: u32 = 93; -pub const R_ARM_PLT32_ABS: u32 = 94; -/// GOT entry. -pub const R_ARM_GOT_ABS: u32 = 95; -/// PC relative GOT entry. -pub const R_ARM_GOT_PREL: u32 = 96; -/// GOT entry relative to GOT origin (`LDR`). -pub const R_ARM_GOT_BREL12: u32 = 97; -/// 12 bit, GOT entry relative to GOT origin (`LDR`, `STR`). -pub const R_ARM_GOTOFF12: u32 = 98; -pub const R_ARM_GOTRELAX: u32 = 99; -pub const R_ARM_GNU_VTENTRY: u32 = 100; -pub const R_ARM_GNU_VTINHERIT: u32 = 101; -/// PC relative & 0xFFE (Thumb16 `B`). -pub const R_ARM_THM_PC11: u32 = 102; -/// PC relative & 0x1FE (Thumb16 `B`/`B`). -pub const R_ARM_THM_PC9: u32 = 103; -/// PC-rel 32 bit for global dynamic thread local data -pub const R_ARM_TLS_GD32: u32 = 104; -/// PC-rel 32 bit for local dynamic thread local data -pub const R_ARM_TLS_LDM32: u32 = 105; -/// 32 bit offset relative to TLS block -pub const R_ARM_TLS_LDO32: u32 = 106; -/// PC-rel 32 bit for GOT entry of static TLS block offset -pub const R_ARM_TLS_IE32: u32 = 107; -/// 32 bit offset relative to static TLS block -pub const R_ARM_TLS_LE32: u32 = 108; -/// 12 bit relative to TLS block (`LDR`, `STR`). -pub const R_ARM_TLS_LDO12: u32 = 109; -/// 12 bit relative to static TLS block (`LDR`, `STR`). -pub const R_ARM_TLS_LE12: u32 = 110; -/// 12 bit GOT entry relative to GOT origin (`LDR`). -pub const R_ARM_TLS_IE12GP: u32 = 111; -/// Obsolete. -pub const R_ARM_ME_TOO: u32 = 128; -pub const R_ARM_THM_TLS_DESCSEQ: u32 = 129; -pub const R_ARM_THM_TLS_DESCSEQ16: u32 = 129; -pub const R_ARM_THM_TLS_DESCSEQ32: u32 = 130; -/// GOT entry relative to GOT origin, 12 bit (Thumb32 `LDR`). -pub const R_ARM_THM_GOT_BREL12: u32 = 131; -pub const R_ARM_IRELATIVE: u32 = 160; -pub const R_ARM_RXPC25: u32 = 249; -pub const R_ARM_RSBREL32: u32 = 250; -pub const R_ARM_THM_RPC22: u32 = 251; -pub const R_ARM_RREL32: u32 = 252; -pub const R_ARM_RABS22: u32 = 253; -pub const R_ARM_RPC24: u32 = 254; -pub const R_ARM_RBASE: u32 = 255; - -// C-SKY values for `Rel*::r_type`. -/// no reloc -pub const R_CKCORE_NONE: u32 = 0; -/// direct 32 bit (S + A) -pub const R_CKCORE_ADDR32: u32 = 1; -/// disp ((S + A - P) >> 2) & 0xff -pub const R_CKCORE_PCRELIMM8BY4: u32 = 2; -/// disp ((S + A - P) >> 1) & 0x7ff -pub const R_CKCORE_PCRELIMM11BY2: u32 = 3; -/// 32-bit rel (S + A - P) -pub const R_CKCORE_PCREL32: u32 = 5; -/// disp ((S + A - P) >>1) & 0x7ff -pub const R_CKCORE_PCRELJSR_IMM11BY2: u32 = 6; -/// 32 bit adjust program base(B + A) -pub const R_CKCORE_RELATIVE: u32 = 9; -/// 32 bit adjust by program base -pub const R_CKCORE_COPY: u32 = 10; -/// off between got and sym (S) -pub const R_CKCORE_GLOB_DAT: u32 = 11; -/// PLT entry (S) -pub const R_CKCORE_JUMP_SLOT: u32 = 12; -/// offset to GOT (S + A - GOT) -pub const R_CKCORE_GOTOFF: u32 = 13; -/// PC offset to GOT (GOT + A - P) -pub const R_CKCORE_GOTPC: u32 = 14; -/// 32 bit GOT entry (G) -pub const R_CKCORE_GOT32: u32 = 15; -/// 32 bit PLT entry (G) -pub const R_CKCORE_PLT32: u32 = 16; -/// GOT entry in GLOB_DAT (GOT + G) -pub const R_CKCORE_ADDRGOT: u32 = 17; -/// PLT entry in GLOB_DAT (GOT + G) -pub const R_CKCORE_ADDRPLT: u32 = 18; -/// ((S + A - P) >> 1) & 0x3ff_ffff -pub const R_CKCORE_PCREL_IMM26BY2: u32 = 19; -/// disp ((S + A - P) >> 1) & 0xffff -pub const R_CKCORE_PCREL_IMM16BY2: u32 = 20; -/// disp ((S + A - P) >> 2) & 0xffff -pub const R_CKCORE_PCREL_IMM16BY4: u32 = 21; -/// disp ((S + A - P) >> 1) & 0x3ff -pub const R_CKCORE_PCREL_IMM10BY2: u32 = 22; -/// disp ((S + A - P) >> 2) & 0x3ff -pub const R_CKCORE_PCREL_IMM10BY4: u32 = 23; -/// high & low 16 bit ADDR, ((S + A) >> 16) & 0xffff -pub const R_CKCORE_ADDR_HI16: u32 = 24; -/// (S + A) & 0xffff -pub const R_CKCORE_ADDR_LO16: u32 = 25; -/// high & low 16 bit GOTPC, ((GOT + A - P) >> 16) & 0xffff -pub const R_CKCORE_GOTPC_HI16: u32 = 26; -/// (GOT + A - P) & 0xffff -pub const R_CKCORE_GOTPC_LO16: u32 = 27; -/// high & low 16 bit GOTOFF, ((S + A - GOT) >> 16) & 0xffff -pub const R_CKCORE_GOTOFF_HI16: u32 = 28; -/// (S + A - GOT) & 0xffff -pub const R_CKCORE_GOTOFF_LO16: u32 = 29; -/// 12 bit disp GOT entry (G) -pub const R_CKCORE_GOT12: u32 = 30; -/// high & low 16 bit GOT, (G >> 16) & 0xffff -pub const R_CKCORE_GOT_HI16: u32 = 31; -/// (G & 0xffff) -pub const R_CKCORE_GOT_LO16: u32 = 32; -/// 12 bit disp PLT entry (G) -pub const R_CKCORE_PLT12: u32 = 33; -/// high & low 16 bit PLT, (G >> 16) & 0xffff -pub const R_CKCORE_PLT_HI16: u32 = 34; -/// G & 0xffff -pub const R_CKCORE_PLT_LO16: u32 = 35; -/// high & low 16 bit ADDRGOT, (GOT + G * 4) & 0xffff -pub const R_CKCORE_ADDRGOT_HI16: u32 = 36; -/// (GOT + G * 4) & 0xffff -pub const R_CKCORE_ADDRGOT_LO16: u32 = 37; -/// high & low 16 bit ADDRPLT, ((GOT + G * 4) >> 16) & 0xFFFF -pub const R_CKCORE_ADDRPLT_HI16: u32 = 38; -/// (GOT+G*4) & 0xffff -pub const R_CKCORE_ADDRPLT_LO16: u32 = 39; -/// disp ((S+A-P) >>1) & x3ff_ffff -pub const R_CKCORE_PCREL_JSR_IMM26BY2: u32 = 40; -/// (S+A-BTEXT) & 0xffff -pub const R_CKCORE_TOFFSET_LO16: u32 = 41; -/// (S+A-BTEXT) & 0xffff -pub const R_CKCORE_DOFFSET_LO16: u32 = 42; -/// disp ((S+A-P) >>1) & 0x3ffff -pub const R_CKCORE_PCREL_IMM18BY2: u32 = 43; -/// disp (S+A-BDATA) & 0x3ffff -pub const R_CKCORE_DOFFSET_IMM18: u32 = 44; -/// disp ((S+A-BDATA)>>1) & 0x3ffff -pub const R_CKCORE_DOFFSET_IMM18BY2: u32 = 45; -/// disp ((S+A-BDATA)>>2) & 0x3ffff -pub const R_CKCORE_DOFFSET_IMM18BY4: u32 = 46; -/// disp (G >> 2) -pub const R_CKCORE_GOT_IMM18BY4: u32 = 48; -/// disp (G >> 2) -pub const R_CKCORE_PLT_IMM18BY4: u32 = 49; -/// disp ((S+A-P) >>2) & 0x7f -pub const R_CKCORE_PCREL_IMM7BY4: u32 = 50; -/// 32 bit offset to TLS block -pub const R_CKCORE_TLS_LE32: u32 = 51; -pub const R_CKCORE_TLS_IE32: u32 = 52; -pub const R_CKCORE_TLS_GD32: u32 = 53; -pub const R_CKCORE_TLS_LDM32: u32 = 54; -pub const R_CKCORE_TLS_LDO32: u32 = 55; -pub const R_CKCORE_TLS_DTPMOD32: u32 = 56; -pub const R_CKCORE_TLS_DTPOFF32: u32 = 57; -pub const R_CKCORE_TLS_TPOFF32: u32 = 58; - -// C-SKY values for `FileHeader*::e_flags`. -pub const EF_CSKY_ABIMASK: u32 = 0xF000_0000; -pub const EF_CSKY_OTHER: u32 = 0x0FFF_0000; -pub const EF_CSKY_PROCESSOR: u32 = 0x0000_FFFF; - -pub const EF_CSKY_ABIV1: u32 = 0x1000_0000; -pub const EF_CSKY_ABIV2: u32 = 0x2000_0000; - -// C-SKY values for `SectionHeader*::sh_type`. -/// C-SKY attributes section. -pub const SHT_CSKY_ATTRIBUTES: u32 = SHT_LOPROC + 1; - -// IA-64 specific declarations. - -// IA-64 values for `FileHeader64::e_flags`. -/// os-specific flags -pub const EF_IA_64_MASKOS: u32 = 0x0000_000f; -/// 64-bit ABI -pub const EF_IA_64_ABI64: u32 = 0x0000_0010; -/// arch. version mask -pub const EF_IA_64_ARCH: u32 = 0xff00_0000; - -// IA-64 values for `ProgramHeader64::p_type`. -/// arch extension bits -pub const PT_IA_64_ARCHEXT: u32 = PT_LOPROC + 0; -/// ia64 unwind bits -pub const PT_IA_64_UNWIND: u32 = PT_LOPROC + 1; -pub const PT_IA_64_HP_OPT_ANOT: u32 = PT_LOOS + 0x12; -pub const PT_IA_64_HP_HSL_ANOT: u32 = PT_LOOS + 0x13; -pub const PT_IA_64_HP_STACK: u32 = PT_LOOS + 0x14; - -// IA-64 values for `ProgramHeader64::p_flags`. -/// spec insns w/o recovery -pub const PF_IA_64_NORECOV: u32 = 0x8000_0000; - -// IA-64 values for `SectionHeader64::sh_type`. -/// extension bits -pub const SHT_IA_64_EXT: u32 = SHT_LOPROC + 0; -/// unwind bits -pub const SHT_IA_64_UNWIND: u32 = SHT_LOPROC + 1; - -// IA-64 values for `SectionHeader64::sh_flags`. -/// section near gp -pub const SHF_IA_64_SHORT: u32 = 0x1000_0000; -/// spec insns w/o recovery -pub const SHF_IA_64_NORECOV: u32 = 0x2000_0000; - -// IA-64 values for `Dyn64::d_tag`. -pub const DT_IA_64_PLT_RESERVE: u32 = DT_LOPROC + 0; - -// IA-64 values for `Rel*::r_type`. -/// none -pub const R_IA64_NONE: u32 = 0x00; -/// symbol + addend, add imm14 -pub const R_IA64_IMM14: u32 = 0x21; -/// symbol + addend, add imm22 -pub const R_IA64_IMM22: u32 = 0x22; -/// symbol + addend, mov imm64 -pub const R_IA64_IMM64: u32 = 0x23; -/// symbol + addend, data4 MSB -pub const R_IA64_DIR32MSB: u32 = 0x24; -/// symbol + addend, data4 LSB -pub const R_IA64_DIR32LSB: u32 = 0x25; -/// symbol + addend, data8 MSB -pub const R_IA64_DIR64MSB: u32 = 0x26; -/// symbol + addend, data8 LSB -pub const R_IA64_DIR64LSB: u32 = 0x27; -/// @gprel(sym + add), add imm22 -pub const R_IA64_GPREL22: u32 = 0x2a; -/// @gprel(sym + add), mov imm64 -pub const R_IA64_GPREL64I: u32 = 0x2b; -/// @gprel(sym + add), data4 MSB -pub const R_IA64_GPREL32MSB: u32 = 0x2c; -/// @gprel(sym + add), data4 LSB -pub const R_IA64_GPREL32LSB: u32 = 0x2d; -/// @gprel(sym + add), data8 MSB -pub const R_IA64_GPREL64MSB: u32 = 0x2e; -/// @gprel(sym + add), data8 LSB -pub const R_IA64_GPREL64LSB: u32 = 0x2f; -/// @ltoff(sym + add), add imm22 -pub const R_IA64_LTOFF22: u32 = 0x32; -/// @ltoff(sym + add), mov imm64 -pub const R_IA64_LTOFF64I: u32 = 0x33; -/// @pltoff(sym + add), add imm22 -pub const R_IA64_PLTOFF22: u32 = 0x3a; -/// @pltoff(sym + add), mov imm64 -pub const R_IA64_PLTOFF64I: u32 = 0x3b; -/// @pltoff(sym + add), data8 MSB -pub const R_IA64_PLTOFF64MSB: u32 = 0x3e; -/// @pltoff(sym + add), data8 LSB -pub const R_IA64_PLTOFF64LSB: u32 = 0x3f; -/// @fptr(sym + add), mov imm64 -pub const R_IA64_FPTR64I: u32 = 0x43; -/// @fptr(sym + add), data4 MSB -pub const R_IA64_FPTR32MSB: u32 = 0x44; -/// @fptr(sym + add), data4 LSB -pub const R_IA64_FPTR32LSB: u32 = 0x45; -/// @fptr(sym + add), data8 MSB -pub const R_IA64_FPTR64MSB: u32 = 0x46; -/// @fptr(sym + add), data8 LSB -pub const R_IA64_FPTR64LSB: u32 = 0x47; -/// @pcrel(sym + add), brl -pub const R_IA64_PCREL60B: u32 = 0x48; -/// @pcrel(sym + add), ptb, call -pub const R_IA64_PCREL21B: u32 = 0x49; -/// @pcrel(sym + add), chk.s -pub const R_IA64_PCREL21M: u32 = 0x4a; -/// @pcrel(sym + add), fchkf -pub const R_IA64_PCREL21F: u32 = 0x4b; -/// @pcrel(sym + add), data4 MSB -pub const R_IA64_PCREL32MSB: u32 = 0x4c; -/// @pcrel(sym + add), data4 LSB -pub const R_IA64_PCREL32LSB: u32 = 0x4d; -/// @pcrel(sym + add), data8 MSB -pub const R_IA64_PCREL64MSB: u32 = 0x4e; -/// @pcrel(sym + add), data8 LSB -pub const R_IA64_PCREL64LSB: u32 = 0x4f; -/// @ltoff(@fptr(s+a)), imm22 -pub const R_IA64_LTOFF_FPTR22: u32 = 0x52; -/// @ltoff(@fptr(s+a)), imm64 -pub const R_IA64_LTOFF_FPTR64I: u32 = 0x53; -/// @ltoff(@fptr(s+a)), data4 MSB -pub const R_IA64_LTOFF_FPTR32MSB: u32 = 0x54; -/// @ltoff(@fptr(s+a)), data4 LSB -pub const R_IA64_LTOFF_FPTR32LSB: u32 = 0x55; -/// @ltoff(@fptr(s+a)), data8 MSB -pub const R_IA64_LTOFF_FPTR64MSB: u32 = 0x56; -/// @ltoff(@fptr(s+a)), data8 LSB -pub const R_IA64_LTOFF_FPTR64LSB: u32 = 0x57; -/// @segrel(sym + add), data4 MSB -pub const R_IA64_SEGREL32MSB: u32 = 0x5c; -/// @segrel(sym + add), data4 LSB -pub const R_IA64_SEGREL32LSB: u32 = 0x5d; -/// @segrel(sym + add), data8 MSB -pub const R_IA64_SEGREL64MSB: u32 = 0x5e; -/// @segrel(sym + add), data8 LSB -pub const R_IA64_SEGREL64LSB: u32 = 0x5f; -/// @secrel(sym + add), data4 MSB -pub const R_IA64_SECREL32MSB: u32 = 0x64; -/// @secrel(sym + add), data4 LSB -pub const R_IA64_SECREL32LSB: u32 = 0x65; -/// @secrel(sym + add), data8 MSB -pub const R_IA64_SECREL64MSB: u32 = 0x66; -/// @secrel(sym + add), data8 LSB -pub const R_IA64_SECREL64LSB: u32 = 0x67; -/// data 4 + REL -pub const R_IA64_REL32MSB: u32 = 0x6c; -/// data 4 + REL -pub const R_IA64_REL32LSB: u32 = 0x6d; -/// data 8 + REL -pub const R_IA64_REL64MSB: u32 = 0x6e; -/// data 8 + REL -pub const R_IA64_REL64LSB: u32 = 0x6f; -/// symbol + addend, data4 MSB -pub const R_IA64_LTV32MSB: u32 = 0x74; -/// symbol + addend, data4 LSB -pub const R_IA64_LTV32LSB: u32 = 0x75; -/// symbol + addend, data8 MSB -pub const R_IA64_LTV64MSB: u32 = 0x76; -/// symbol + addend, data8 LSB -pub const R_IA64_LTV64LSB: u32 = 0x77; -/// @pcrel(sym + add), 21bit inst -pub const R_IA64_PCREL21BI: u32 = 0x79; -/// @pcrel(sym + add), 22bit inst -pub const R_IA64_PCREL22: u32 = 0x7a; -/// @pcrel(sym + add), 64bit inst -pub const R_IA64_PCREL64I: u32 = 0x7b; -/// dynamic reloc, imported PLT, MSB -pub const R_IA64_IPLTMSB: u32 = 0x80; -/// dynamic reloc, imported PLT, LSB -pub const R_IA64_IPLTLSB: u32 = 0x81; -/// copy relocation -pub const R_IA64_COPY: u32 = 0x84; -/// Addend and symbol difference -pub const R_IA64_SUB: u32 = 0x85; -/// LTOFF22, relaxable. -pub const R_IA64_LTOFF22X: u32 = 0x86; -/// Use of LTOFF22X. -pub const R_IA64_LDXMOV: u32 = 0x87; -/// @tprel(sym + add), imm14 -pub const R_IA64_TPREL14: u32 = 0x91; -/// @tprel(sym + add), imm22 -pub const R_IA64_TPREL22: u32 = 0x92; -/// @tprel(sym + add), imm64 -pub const R_IA64_TPREL64I: u32 = 0x93; -/// @tprel(sym + add), data8 MSB -pub const R_IA64_TPREL64MSB: u32 = 0x96; -/// @tprel(sym + add), data8 LSB -pub const R_IA64_TPREL64LSB: u32 = 0x97; -/// @ltoff(@tprel(s+a)), imm2 -pub const R_IA64_LTOFF_TPREL22: u32 = 0x9a; -/// @dtpmod(sym + add), data8 MSB -pub const R_IA64_DTPMOD64MSB: u32 = 0xa6; -/// @dtpmod(sym + add), data8 LSB -pub const R_IA64_DTPMOD64LSB: u32 = 0xa7; -/// @ltoff(@dtpmod(sym + add)), imm22 -pub const R_IA64_LTOFF_DTPMOD22: u32 = 0xaa; -/// @dtprel(sym + add), imm14 -pub const R_IA64_DTPREL14: u32 = 0xb1; -/// @dtprel(sym + add), imm22 -pub const R_IA64_DTPREL22: u32 = 0xb2; -/// @dtprel(sym + add), imm64 -pub const R_IA64_DTPREL64I: u32 = 0xb3; -/// @dtprel(sym + add), data4 MSB -pub const R_IA64_DTPREL32MSB: u32 = 0xb4; -/// @dtprel(sym + add), data4 LSB -pub const R_IA64_DTPREL32LSB: u32 = 0xb5; -/// @dtprel(sym + add), data8 MSB -pub const R_IA64_DTPREL64MSB: u32 = 0xb6; -/// @dtprel(sym + add), data8 LSB -pub const R_IA64_DTPREL64LSB: u32 = 0xb7; -/// @ltoff(@dtprel(s+a)), imm22 -pub const R_IA64_LTOFF_DTPREL22: u32 = 0xba; - -// SH specific declarations. - -// SH values `FileHeader*::e_flags`. -pub const EF_SH_MACH_MASK: u32 = 0x1f; -pub const EF_SH_UNKNOWN: u32 = 0x0; -pub const EF_SH1: u32 = 0x1; -pub const EF_SH2: u32 = 0x2; -pub const EF_SH3: u32 = 0x3; -pub const EF_SH_DSP: u32 = 0x4; -pub const EF_SH3_DSP: u32 = 0x5; -pub const EF_SH4AL_DSP: u32 = 0x6; -pub const EF_SH3E: u32 = 0x8; -pub const EF_SH4: u32 = 0x9; -pub const EF_SH2E: u32 = 0xb; -pub const EF_SH4A: u32 = 0xc; -pub const EF_SH2A: u32 = 0xd; -pub const EF_SH4_NOFPU: u32 = 0x10; -pub const EF_SH4A_NOFPU: u32 = 0x11; -pub const EF_SH4_NOMMU_NOFPU: u32 = 0x12; -pub const EF_SH2A_NOFPU: u32 = 0x13; -pub const EF_SH3_NOMMU: u32 = 0x14; -pub const EF_SH2A_SH4_NOFPU: u32 = 0x15; -pub const EF_SH2A_SH3_NOFPU: u32 = 0x16; -pub const EF_SH2A_SH4: u32 = 0x17; -pub const EF_SH2A_SH3E: u32 = 0x18; - -// SH values `Rel*::r_type`. -pub const R_SH_NONE: u32 = 0; -pub const R_SH_DIR32: u32 = 1; -pub const R_SH_REL32: u32 = 2; -pub const R_SH_DIR8WPN: u32 = 3; -pub const R_SH_IND12W: u32 = 4; -pub const R_SH_DIR8WPL: u32 = 5; -pub const R_SH_DIR8WPZ: u32 = 6; -pub const R_SH_DIR8BP: u32 = 7; -pub const R_SH_DIR8W: u32 = 8; -pub const R_SH_DIR8L: u32 = 9; -pub const R_SH_SWITCH16: u32 = 25; -pub const R_SH_SWITCH32: u32 = 26; -pub const R_SH_USES: u32 = 27; -pub const R_SH_COUNT: u32 = 28; -pub const R_SH_ALIGN: u32 = 29; -pub const R_SH_CODE: u32 = 30; -pub const R_SH_DATA: u32 = 31; -pub const R_SH_LABEL: u32 = 32; -pub const R_SH_SWITCH8: u32 = 33; -pub const R_SH_GNU_VTINHERIT: u32 = 34; -pub const R_SH_GNU_VTENTRY: u32 = 35; -pub const R_SH_TLS_GD_32: u32 = 144; -pub const R_SH_TLS_LD_32: u32 = 145; -pub const R_SH_TLS_LDO_32: u32 = 146; -pub const R_SH_TLS_IE_32: u32 = 147; -pub const R_SH_TLS_LE_32: u32 = 148; -pub const R_SH_TLS_DTPMOD32: u32 = 149; -pub const R_SH_TLS_DTPOFF32: u32 = 150; -pub const R_SH_TLS_TPOFF32: u32 = 151; -pub const R_SH_GOT32: u32 = 160; -pub const R_SH_PLT32: u32 = 161; -pub const R_SH_COPY: u32 = 162; -pub const R_SH_GLOB_DAT: u32 = 163; -pub const R_SH_JMP_SLOT: u32 = 164; -pub const R_SH_RELATIVE: u32 = 165; -pub const R_SH_GOTOFF: u32 = 166; -pub const R_SH_GOTPC: u32 = 167; - -// S/390 specific definitions. - -// S/390 values `FileHeader*::e_flags`. - -/// High GPRs kernel facility needed. -pub const EF_S390_HIGH_GPRS: u32 = 0x0000_0001; - -// S/390 values `Rel*::r_type`. - -/// No reloc. -pub const R_390_NONE: u32 = 0; -/// Direct 8 bit. -pub const R_390_8: u32 = 1; -/// Direct 12 bit. -pub const R_390_12: u32 = 2; -/// Direct 16 bit. -pub const R_390_16: u32 = 3; -/// Direct 32 bit. -pub const R_390_32: u32 = 4; -/// PC relative 32 bit. -pub const R_390_PC32: u32 = 5; -/// 12 bit GOT offset. -pub const R_390_GOT12: u32 = 6; -/// 32 bit GOT offset. -pub const R_390_GOT32: u32 = 7; -/// 32 bit PC relative PLT address. -pub const R_390_PLT32: u32 = 8; -/// Copy symbol at runtime. -pub const R_390_COPY: u32 = 9; -/// Create GOT entry. -pub const R_390_GLOB_DAT: u32 = 10; -/// Create PLT entry. -pub const R_390_JMP_SLOT: u32 = 11; -/// Adjust by program base. -pub const R_390_RELATIVE: u32 = 12; -/// 32 bit offset to GOT. -pub const R_390_GOTOFF32: u32 = 13; -/// 32 bit PC relative offset to GOT. -pub const R_390_GOTPC: u32 = 14; -/// 16 bit GOT offset. -pub const R_390_GOT16: u32 = 15; -/// PC relative 16 bit. -pub const R_390_PC16: u32 = 16; -/// PC relative 16 bit shifted by 1. -pub const R_390_PC16DBL: u32 = 17; -/// 16 bit PC rel. PLT shifted by 1. -pub const R_390_PLT16DBL: u32 = 18; -/// PC relative 32 bit shifted by 1. -pub const R_390_PC32DBL: u32 = 19; -/// 32 bit PC rel. PLT shifted by 1. -pub const R_390_PLT32DBL: u32 = 20; -/// 32 bit PC rel. GOT shifted by 1. -pub const R_390_GOTPCDBL: u32 = 21; -/// Direct 64 bit. -pub const R_390_64: u32 = 22; -/// PC relative 64 bit. -pub const R_390_PC64: u32 = 23; -/// 64 bit GOT offset. -pub const R_390_GOT64: u32 = 24; -/// 64 bit PC relative PLT address. -pub const R_390_PLT64: u32 = 25; -/// 32 bit PC rel. to GOT entry >> 1. -pub const R_390_GOTENT: u32 = 26; -/// 16 bit offset to GOT. -pub const R_390_GOTOFF16: u32 = 27; -/// 64 bit offset to GOT. -pub const R_390_GOTOFF64: u32 = 28; -/// 12 bit offset to jump slot. -pub const R_390_GOTPLT12: u32 = 29; -/// 16 bit offset to jump slot. -pub const R_390_GOTPLT16: u32 = 30; -/// 32 bit offset to jump slot. -pub const R_390_GOTPLT32: u32 = 31; -/// 64 bit offset to jump slot. -pub const R_390_GOTPLT64: u32 = 32; -/// 32 bit rel. offset to jump slot. -pub const R_390_GOTPLTENT: u32 = 33; -/// 16 bit offset from GOT to PLT. -pub const R_390_PLTOFF16: u32 = 34; -/// 32 bit offset from GOT to PLT. -pub const R_390_PLTOFF32: u32 = 35; -/// 16 bit offset from GOT to PLT. -pub const R_390_PLTOFF64: u32 = 36; -/// Tag for load insn in TLS code. -pub const R_390_TLS_LOAD: u32 = 37; -/// Tag for function call in general dynamic TLS code. -pub const R_390_TLS_GDCALL: u32 = 38; -/// Tag for function call in local dynamic TLS code. -pub const R_390_TLS_LDCALL: u32 = 39; -/// Direct 32 bit for general dynamic thread local data. -pub const R_390_TLS_GD32: u32 = 40; -/// Direct 64 bit for general dynamic thread local data. -pub const R_390_TLS_GD64: u32 = 41; -/// 12 bit GOT offset for static TLS block offset. -pub const R_390_TLS_GOTIE12: u32 = 42; -/// 32 bit GOT offset for static TLS block offset. -pub const R_390_TLS_GOTIE32: u32 = 43; -/// 64 bit GOT offset for static TLS block offset. -pub const R_390_TLS_GOTIE64: u32 = 44; -/// Direct 32 bit for local dynamic thread local data in LE code. -pub const R_390_TLS_LDM32: u32 = 45; -/// Direct 64 bit for local dynamic thread local data in LE code. -pub const R_390_TLS_LDM64: u32 = 46; -/// 32 bit address of GOT entry for negated static TLS block offset. -pub const R_390_TLS_IE32: u32 = 47; -/// 64 bit address of GOT entry for negated static TLS block offset. -pub const R_390_TLS_IE64: u32 = 48; -/// 32 bit rel. offset to GOT entry for negated static TLS block offset. -pub const R_390_TLS_IEENT: u32 = 49; -/// 32 bit negated offset relative to static TLS block. -pub const R_390_TLS_LE32: u32 = 50; -/// 64 bit negated offset relative to static TLS block. -pub const R_390_TLS_LE64: u32 = 51; -/// 32 bit offset relative to TLS block. -pub const R_390_TLS_LDO32: u32 = 52; -/// 64 bit offset relative to TLS block. -pub const R_390_TLS_LDO64: u32 = 53; -/// ID of module containing symbol. -pub const R_390_TLS_DTPMOD: u32 = 54; -/// Offset in TLS block. -pub const R_390_TLS_DTPOFF: u32 = 55; -/// Negated offset in static TLS block. -pub const R_390_TLS_TPOFF: u32 = 56; -/// Direct 20 bit. -pub const R_390_20: u32 = 57; -/// 20 bit GOT offset. -pub const R_390_GOT20: u32 = 58; -/// 20 bit offset to jump slot. -pub const R_390_GOTPLT20: u32 = 59; -/// 20 bit GOT offset for static TLS block offset. -pub const R_390_TLS_GOTIE20: u32 = 60; -/// STT_GNU_IFUNC relocation. -pub const R_390_IRELATIVE: u32 = 61; - -// CRIS values `Rel*::r_type`. -pub const R_CRIS_NONE: u32 = 0; -pub const R_CRIS_8: u32 = 1; -pub const R_CRIS_16: u32 = 2; -pub const R_CRIS_32: u32 = 3; -pub const R_CRIS_8_PCREL: u32 = 4; -pub const R_CRIS_16_PCREL: u32 = 5; -pub const R_CRIS_32_PCREL: u32 = 6; -pub const R_CRIS_GNU_VTINHERIT: u32 = 7; -pub const R_CRIS_GNU_VTENTRY: u32 = 8; -pub const R_CRIS_COPY: u32 = 9; -pub const R_CRIS_GLOB_DAT: u32 = 10; -pub const R_CRIS_JUMP_SLOT: u32 = 11; -pub const R_CRIS_RELATIVE: u32 = 12; -pub const R_CRIS_16_GOT: u32 = 13; -pub const R_CRIS_32_GOT: u32 = 14; -pub const R_CRIS_16_GOTPLT: u32 = 15; -pub const R_CRIS_32_GOTPLT: u32 = 16; -pub const R_CRIS_32_GOTREL: u32 = 17; -pub const R_CRIS_32_PLT_GOTREL: u32 = 18; -pub const R_CRIS_32_PLT_PCREL: u32 = 19; - -// AMD x86-64 values `Rel*::r_type`. -/// No reloc -pub const R_X86_64_NONE: u32 = 0; -/// Direct 64 bit -pub const R_X86_64_64: u32 = 1; -/// PC relative 32 bit signed -pub const R_X86_64_PC32: u32 = 2; -/// 32 bit GOT entry -pub const R_X86_64_GOT32: u32 = 3; -/// 32 bit PLT address -pub const R_X86_64_PLT32: u32 = 4; -/// Copy symbol at runtime -pub const R_X86_64_COPY: u32 = 5; -/// Create GOT entry -pub const R_X86_64_GLOB_DAT: u32 = 6; -/// Create PLT entry -pub const R_X86_64_JUMP_SLOT: u32 = 7; -/// Adjust by program base -pub const R_X86_64_RELATIVE: u32 = 8; -/// 32 bit signed PC relative offset to GOT -pub const R_X86_64_GOTPCREL: u32 = 9; -/// Direct 32 bit zero extended -pub const R_X86_64_32: u32 = 10; -/// Direct 32 bit sign extended -pub const R_X86_64_32S: u32 = 11; -/// Direct 16 bit zero extended -pub const R_X86_64_16: u32 = 12; -/// 16 bit sign extended pc relative -pub const R_X86_64_PC16: u32 = 13; -/// Direct 8 bit sign extended -pub const R_X86_64_8: u32 = 14; -/// 8 bit sign extended pc relative -pub const R_X86_64_PC8: u32 = 15; -/// ID of module containing symbol -pub const R_X86_64_DTPMOD64: u32 = 16; -/// Offset in module's TLS block -pub const R_X86_64_DTPOFF64: u32 = 17; -/// Offset in initial TLS block -pub const R_X86_64_TPOFF64: u32 = 18; -/// 32 bit signed PC relative offset to two GOT entries for GD symbol -pub const R_X86_64_TLSGD: u32 = 19; -/// 32 bit signed PC relative offset to two GOT entries for LD symbol -pub const R_X86_64_TLSLD: u32 = 20; -/// Offset in TLS block -pub const R_X86_64_DTPOFF32: u32 = 21; -/// 32 bit signed PC relative offset to GOT entry for IE symbol -pub const R_X86_64_GOTTPOFF: u32 = 22; -/// Offset in initial TLS block -pub const R_X86_64_TPOFF32: u32 = 23; -/// PC relative 64 bit -pub const R_X86_64_PC64: u32 = 24; -/// 64 bit offset to GOT -pub const R_X86_64_GOTOFF64: u32 = 25; -/// 32 bit signed pc relative offset to GOT -pub const R_X86_64_GOTPC32: u32 = 26; -/// 64-bit GOT entry offset -pub const R_X86_64_GOT64: u32 = 27; -/// 64-bit PC relative offset to GOT entry -pub const R_X86_64_GOTPCREL64: u32 = 28; -/// 64-bit PC relative offset to GOT -pub const R_X86_64_GOTPC64: u32 = 29; -/// like GOT64, says PLT entry needed -pub const R_X86_64_GOTPLT64: u32 = 30; -/// 64-bit GOT relative offset to PLT entry -pub const R_X86_64_PLTOFF64: u32 = 31; -/// Size of symbol plus 32-bit addend -pub const R_X86_64_SIZE32: u32 = 32; -/// Size of symbol plus 64-bit addend -pub const R_X86_64_SIZE64: u32 = 33; -/// GOT offset for TLS descriptor. -pub const R_X86_64_GOTPC32_TLSDESC: u32 = 34; -/// Marker for call through TLS descriptor. -pub const R_X86_64_TLSDESC_CALL: u32 = 35; -/// TLS descriptor. -pub const R_X86_64_TLSDESC: u32 = 36; -/// Adjust indirectly by program base -pub const R_X86_64_IRELATIVE: u32 = 37; -/// 64-bit adjust by program base -pub const R_X86_64_RELATIVE64: u32 = 38; -// 39 Reserved was R_X86_64_PC32_BND -// 40 Reserved was R_X86_64_PLT32_BND -/// Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. -pub const R_X86_64_GOTPCRELX: u32 = 41; -/// Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. -pub const R_X86_64_REX_GOTPCRELX: u32 = 42; - -// AMD x86-64 values `SectionHeader*::sh_type`. -/// Unwind information. -pub const SHT_X86_64_UNWIND: u32 = 0x7000_0001; - -// AM33 values `Rel*::r_type`. -/// No reloc. -pub const R_MN10300_NONE: u32 = 0; -/// Direct 32 bit. -pub const R_MN10300_32: u32 = 1; -/// Direct 16 bit. -pub const R_MN10300_16: u32 = 2; -/// Direct 8 bit. -pub const R_MN10300_8: u32 = 3; -/// PC-relative 32-bit. -pub const R_MN10300_PCREL32: u32 = 4; -/// PC-relative 16-bit signed. -pub const R_MN10300_PCREL16: u32 = 5; -/// PC-relative 8-bit signed. -pub const R_MN10300_PCREL8: u32 = 6; -/// Ancient C++ vtable garbage... -pub const R_MN10300_GNU_VTINHERIT: u32 = 7; -/// ... collection annotation. -pub const R_MN10300_GNU_VTENTRY: u32 = 8; -/// Direct 24 bit. -pub const R_MN10300_24: u32 = 9; -/// 32-bit PCrel offset to GOT. -pub const R_MN10300_GOTPC32: u32 = 10; -/// 16-bit PCrel offset to GOT. -pub const R_MN10300_GOTPC16: u32 = 11; -/// 32-bit offset from GOT. -pub const R_MN10300_GOTOFF32: u32 = 12; -/// 24-bit offset from GOT. -pub const R_MN10300_GOTOFF24: u32 = 13; -/// 16-bit offset from GOT. -pub const R_MN10300_GOTOFF16: u32 = 14; -/// 32-bit PCrel to PLT entry. -pub const R_MN10300_PLT32: u32 = 15; -/// 16-bit PCrel to PLT entry. -pub const R_MN10300_PLT16: u32 = 16; -/// 32-bit offset to GOT entry. -pub const R_MN10300_GOT32: u32 = 17; -/// 24-bit offset to GOT entry. -pub const R_MN10300_GOT24: u32 = 18; -/// 16-bit offset to GOT entry. -pub const R_MN10300_GOT16: u32 = 19; -/// Copy symbol at runtime. -pub const R_MN10300_COPY: u32 = 20; -/// Create GOT entry. -pub const R_MN10300_GLOB_DAT: u32 = 21; -/// Create PLT entry. -pub const R_MN10300_JMP_SLOT: u32 = 22; -/// Adjust by program base. -pub const R_MN10300_RELATIVE: u32 = 23; -/// 32-bit offset for global dynamic. -pub const R_MN10300_TLS_GD: u32 = 24; -/// 32-bit offset for local dynamic. -pub const R_MN10300_TLS_LD: u32 = 25; -/// Module-relative offset. -pub const R_MN10300_TLS_LDO: u32 = 26; -/// GOT offset for static TLS block offset. -pub const R_MN10300_TLS_GOTIE: u32 = 27; -/// GOT address for static TLS block offset. -pub const R_MN10300_TLS_IE: u32 = 28; -/// Offset relative to static TLS block. -pub const R_MN10300_TLS_LE: u32 = 29; -/// ID of module containing symbol. -pub const R_MN10300_TLS_DTPMOD: u32 = 30; -/// Offset in module TLS block. -pub const R_MN10300_TLS_DTPOFF: u32 = 31; -/// Offset in static TLS block. -pub const R_MN10300_TLS_TPOFF: u32 = 32; -/// Adjustment for next reloc as needed by linker relaxation. -pub const R_MN10300_SYM_DIFF: u32 = 33; -/// Alignment requirement for linker relaxation. -pub const R_MN10300_ALIGN: u32 = 34; - -// M32R values `Rel32::r_type`. -/// No reloc. -pub const R_M32R_NONE: u32 = 0; -/// Direct 16 bit. -pub const R_M32R_16: u32 = 1; -/// Direct 32 bit. -pub const R_M32R_32: u32 = 2; -/// Direct 24 bit. -pub const R_M32R_24: u32 = 3; -/// PC relative 10 bit shifted. -pub const R_M32R_10_PCREL: u32 = 4; -/// PC relative 18 bit shifted. -pub const R_M32R_18_PCREL: u32 = 5; -/// PC relative 26 bit shifted. -pub const R_M32R_26_PCREL: u32 = 6; -/// High 16 bit with unsigned low. -pub const R_M32R_HI16_ULO: u32 = 7; -/// High 16 bit with signed low. -pub const R_M32R_HI16_SLO: u32 = 8; -/// Low 16 bit. -pub const R_M32R_LO16: u32 = 9; -/// 16 bit offset in SDA. -pub const R_M32R_SDA16: u32 = 10; -pub const R_M32R_GNU_VTINHERIT: u32 = 11; -pub const R_M32R_GNU_VTENTRY: u32 = 12; -// M32R values `Rela32::r_type`. -/// Direct 16 bit. -pub const R_M32R_16_RELA: u32 = 33; -/// Direct 32 bit. -pub const R_M32R_32_RELA: u32 = 34; -/// Direct 24 bit. -pub const R_M32R_24_RELA: u32 = 35; -/// PC relative 10 bit shifted. -pub const R_M32R_10_PCREL_RELA: u32 = 36; -/// PC relative 18 bit shifted. -pub const R_M32R_18_PCREL_RELA: u32 = 37; -/// PC relative 26 bit shifted. -pub const R_M32R_26_PCREL_RELA: u32 = 38; -/// High 16 bit with unsigned low -pub const R_M32R_HI16_ULO_RELA: u32 = 39; -/// High 16 bit with signed low -pub const R_M32R_HI16_SLO_RELA: u32 = 40; -/// Low 16 bit -pub const R_M32R_LO16_RELA: u32 = 41; -/// 16 bit offset in SDA -pub const R_M32R_SDA16_RELA: u32 = 42; -pub const R_M32R_RELA_GNU_VTINHERIT: u32 = 43; -pub const R_M32R_RELA_GNU_VTENTRY: u32 = 44; -/// PC relative 32 bit. -pub const R_M32R_REL32: u32 = 45; - -/// 24 bit GOT entry -pub const R_M32R_GOT24: u32 = 48; -/// 26 bit PC relative to PLT shifted -pub const R_M32R_26_PLTREL: u32 = 49; -/// Copy symbol at runtime -pub const R_M32R_COPY: u32 = 50; -/// Create GOT entry -pub const R_M32R_GLOB_DAT: u32 = 51; -/// Create PLT entry -pub const R_M32R_JMP_SLOT: u32 = 52; -/// Adjust by program base -pub const R_M32R_RELATIVE: u32 = 53; -/// 24 bit offset to GOT -pub const R_M32R_GOTOFF: u32 = 54; -/// 24 bit PC relative offset to GOT -pub const R_M32R_GOTPC24: u32 = 55; -/// High 16 bit GOT entry with unsigned low -pub const R_M32R_GOT16_HI_ULO: u32 = 56; -/// High 16 bit GOT entry with signed low -pub const R_M32R_GOT16_HI_SLO: u32 = 57; -/// Low 16 bit GOT entry -pub const R_M32R_GOT16_LO: u32 = 58; -/// High 16 bit PC relative offset to GOT with unsigned low -pub const R_M32R_GOTPC_HI_ULO: u32 = 59; -/// High 16 bit PC relative offset to GOT with signed low -pub const R_M32R_GOTPC_HI_SLO: u32 = 60; -/// Low 16 bit PC relative offset to GOT -pub const R_M32R_GOTPC_LO: u32 = 61; -/// High 16 bit offset to GOT with unsigned low -pub const R_M32R_GOTOFF_HI_ULO: u32 = 62; -/// High 16 bit offset to GOT with signed low -pub const R_M32R_GOTOFF_HI_SLO: u32 = 63; -/// Low 16 bit offset to GOT -pub const R_M32R_GOTOFF_LO: u32 = 64; -/// Keep this the last entry. -pub const R_M32R_NUM: u32 = 256; - -// MicroBlaze values `Rel*::r_type`. -/// No reloc. -pub const R_MICROBLAZE_NONE: u32 = 0; -/// Direct 32 bit. -pub const R_MICROBLAZE_32: u32 = 1; -/// PC relative 32 bit. -pub const R_MICROBLAZE_32_PCREL: u32 = 2; -/// PC relative 64 bit. -pub const R_MICROBLAZE_64_PCREL: u32 = 3; -/// Low 16 bits of PCREL32. -pub const R_MICROBLAZE_32_PCREL_LO: u32 = 4; -/// Direct 64 bit. -pub const R_MICROBLAZE_64: u32 = 5; -/// Low 16 bit. -pub const R_MICROBLAZE_32_LO: u32 = 6; -/// Read-only small data area. -pub const R_MICROBLAZE_SRO32: u32 = 7; -/// Read-write small data area. -pub const R_MICROBLAZE_SRW32: u32 = 8; -/// No reloc. -pub const R_MICROBLAZE_64_NONE: u32 = 9; -/// Symbol Op Symbol relocation. -pub const R_MICROBLAZE_32_SYM_OP_SYM: u32 = 10; -/// GNU C++ vtable hierarchy. -pub const R_MICROBLAZE_GNU_VTINHERIT: u32 = 11; -/// GNU C++ vtable member usage. -pub const R_MICROBLAZE_GNU_VTENTRY: u32 = 12; -/// PC-relative GOT offset. -pub const R_MICROBLAZE_GOTPC_64: u32 = 13; -/// GOT entry offset. -pub const R_MICROBLAZE_GOT_64: u32 = 14; -/// PLT offset (PC-relative). -pub const R_MICROBLAZE_PLT_64: u32 = 15; -/// Adjust by program base. -pub const R_MICROBLAZE_REL: u32 = 16; -/// Create PLT entry. -pub const R_MICROBLAZE_JUMP_SLOT: u32 = 17; -/// Create GOT entry. -pub const R_MICROBLAZE_GLOB_DAT: u32 = 18; -/// 64 bit offset to GOT. -pub const R_MICROBLAZE_GOTOFF_64: u32 = 19; -/// 32 bit offset to GOT. -pub const R_MICROBLAZE_GOTOFF_32: u32 = 20; -/// Runtime copy. -pub const R_MICROBLAZE_COPY: u32 = 21; -/// TLS Reloc. -pub const R_MICROBLAZE_TLS: u32 = 22; -/// TLS General Dynamic. -pub const R_MICROBLAZE_TLSGD: u32 = 23; -/// TLS Local Dynamic. -pub const R_MICROBLAZE_TLSLD: u32 = 24; -/// TLS Module ID. -pub const R_MICROBLAZE_TLSDTPMOD32: u32 = 25; -/// TLS Offset Within TLS Block. -pub const R_MICROBLAZE_TLSDTPREL32: u32 = 26; -/// TLS Offset Within TLS Block. -pub const R_MICROBLAZE_TLSDTPREL64: u32 = 27; -/// TLS Offset From Thread Pointer. -pub const R_MICROBLAZE_TLSGOTTPREL32: u32 = 28; -/// TLS Offset From Thread Pointer. -pub const R_MICROBLAZE_TLSTPREL32: u32 = 29; - -// Nios II values `Dyn::d_tag`. -/// Address of _gp. -pub const DT_NIOS2_GP: u32 = 0x7000_0002; - -// Nios II values `Rel*::r_type`. -/// No reloc. -pub const R_NIOS2_NONE: u32 = 0; -/// Direct signed 16 bit. -pub const R_NIOS2_S16: u32 = 1; -/// Direct unsigned 16 bit. -pub const R_NIOS2_U16: u32 = 2; -/// PC relative 16 bit. -pub const R_NIOS2_PCREL16: u32 = 3; -/// Direct call. -pub const R_NIOS2_CALL26: u32 = 4; -/// 5 bit constant expression. -pub const R_NIOS2_IMM5: u32 = 5; -/// 5 bit expression, shift 22. -pub const R_NIOS2_CACHE_OPX: u32 = 6; -/// 6 bit constant expression. -pub const R_NIOS2_IMM6: u32 = 7; -/// 8 bit constant expression. -pub const R_NIOS2_IMM8: u32 = 8; -/// High 16 bit. -pub const R_NIOS2_HI16: u32 = 9; -/// Low 16 bit. -pub const R_NIOS2_LO16: u32 = 10; -/// High 16 bit, adjusted. -pub const R_NIOS2_HIADJ16: u32 = 11; -/// 32 bit symbol value + addend. -pub const R_NIOS2_BFD_RELOC_32: u32 = 12; -/// 16 bit symbol value + addend. -pub const R_NIOS2_BFD_RELOC_16: u32 = 13; -/// 8 bit symbol value + addend. -pub const R_NIOS2_BFD_RELOC_8: u32 = 14; -/// 16 bit GP pointer offset. -pub const R_NIOS2_GPREL: u32 = 15; -/// GNU C++ vtable hierarchy. -pub const R_NIOS2_GNU_VTINHERIT: u32 = 16; -/// GNU C++ vtable member usage. -pub const R_NIOS2_GNU_VTENTRY: u32 = 17; -/// Unconditional branch. -pub const R_NIOS2_UJMP: u32 = 18; -/// Conditional branch. -pub const R_NIOS2_CJMP: u32 = 19; -/// Indirect call through register. -pub const R_NIOS2_CALLR: u32 = 20; -/// Alignment requirement for linker relaxation. -pub const R_NIOS2_ALIGN: u32 = 21; -/// 16 bit GOT entry. -pub const R_NIOS2_GOT16: u32 = 22; -/// 16 bit GOT entry for function. -pub const R_NIOS2_CALL16: u32 = 23; -/// %lo of offset to GOT pointer. -pub const R_NIOS2_GOTOFF_LO: u32 = 24; -/// %hiadj of offset to GOT pointer. -pub const R_NIOS2_GOTOFF_HA: u32 = 25; -/// %lo of PC relative offset. -pub const R_NIOS2_PCREL_LO: u32 = 26; -/// %hiadj of PC relative offset. -pub const R_NIOS2_PCREL_HA: u32 = 27; -/// 16 bit GOT offset for TLS GD. -pub const R_NIOS2_TLS_GD16: u32 = 28; -/// 16 bit GOT offset for TLS LDM. -pub const R_NIOS2_TLS_LDM16: u32 = 29; -/// 16 bit module relative offset. -pub const R_NIOS2_TLS_LDO16: u32 = 30; -/// 16 bit GOT offset for TLS IE. -pub const R_NIOS2_TLS_IE16: u32 = 31; -/// 16 bit LE TP-relative offset. -pub const R_NIOS2_TLS_LE16: u32 = 32; -/// Module number. -pub const R_NIOS2_TLS_DTPMOD: u32 = 33; -/// Module-relative offset. -pub const R_NIOS2_TLS_DTPREL: u32 = 34; -/// TP-relative offset. -pub const R_NIOS2_TLS_TPREL: u32 = 35; -/// Copy symbol at runtime. -pub const R_NIOS2_COPY: u32 = 36; -/// Create GOT entry. -pub const R_NIOS2_GLOB_DAT: u32 = 37; -/// Create PLT entry. -pub const R_NIOS2_JUMP_SLOT: u32 = 38; -/// Adjust by program base. -pub const R_NIOS2_RELATIVE: u32 = 39; -/// 16 bit offset to GOT pointer. -pub const R_NIOS2_GOTOFF: u32 = 40; -/// Direct call in .noat section. -pub const R_NIOS2_CALL26_NOAT: u32 = 41; -/// %lo() of GOT entry. -pub const R_NIOS2_GOT_LO: u32 = 42; -/// %hiadj() of GOT entry. -pub const R_NIOS2_GOT_HA: u32 = 43; -/// %lo() of function GOT entry. -pub const R_NIOS2_CALL_LO: u32 = 44; -/// %hiadj() of function GOT entry. -pub const R_NIOS2_CALL_HA: u32 = 45; - -// TILEPro values `Rel*::r_type`. -/// No reloc -pub const R_TILEPRO_NONE: u32 = 0; -/// Direct 32 bit -pub const R_TILEPRO_32: u32 = 1; -/// Direct 16 bit -pub const R_TILEPRO_16: u32 = 2; -/// Direct 8 bit -pub const R_TILEPRO_8: u32 = 3; -/// PC relative 32 bit -pub const R_TILEPRO_32_PCREL: u32 = 4; -/// PC relative 16 bit -pub const R_TILEPRO_16_PCREL: u32 = 5; -/// PC relative 8 bit -pub const R_TILEPRO_8_PCREL: u32 = 6; -/// Low 16 bit -pub const R_TILEPRO_LO16: u32 = 7; -/// High 16 bit -pub const R_TILEPRO_HI16: u32 = 8; -/// High 16 bit, adjusted -pub const R_TILEPRO_HA16: u32 = 9; -/// Copy relocation -pub const R_TILEPRO_COPY: u32 = 10; -/// Create GOT entry -pub const R_TILEPRO_GLOB_DAT: u32 = 11; -/// Create PLT entry -pub const R_TILEPRO_JMP_SLOT: u32 = 12; -/// Adjust by program base -pub const R_TILEPRO_RELATIVE: u32 = 13; -/// X1 pipe branch offset -pub const R_TILEPRO_BROFF_X1: u32 = 14; -/// X1 pipe jump offset -pub const R_TILEPRO_JOFFLONG_X1: u32 = 15; -/// X1 pipe jump offset to PLT -pub const R_TILEPRO_JOFFLONG_X1_PLT: u32 = 16; -/// X0 pipe 8-bit -pub const R_TILEPRO_IMM8_X0: u32 = 17; -/// Y0 pipe 8-bit -pub const R_TILEPRO_IMM8_Y0: u32 = 18; -/// X1 pipe 8-bit -pub const R_TILEPRO_IMM8_X1: u32 = 19; -/// Y1 pipe 8-bit -pub const R_TILEPRO_IMM8_Y1: u32 = 20; -/// X1 pipe mtspr -pub const R_TILEPRO_MT_IMM15_X1: u32 = 21; -/// X1 pipe mfspr -pub const R_TILEPRO_MF_IMM15_X1: u32 = 22; -/// X0 pipe 16-bit -pub const R_TILEPRO_IMM16_X0: u32 = 23; -/// X1 pipe 16-bit -pub const R_TILEPRO_IMM16_X1: u32 = 24; -/// X0 pipe low 16-bit -pub const R_TILEPRO_IMM16_X0_LO: u32 = 25; -/// X1 pipe low 16-bit -pub const R_TILEPRO_IMM16_X1_LO: u32 = 26; -/// X0 pipe high 16-bit -pub const R_TILEPRO_IMM16_X0_HI: u32 = 27; -/// X1 pipe high 16-bit -pub const R_TILEPRO_IMM16_X1_HI: u32 = 28; -/// X0 pipe high 16-bit, adjusted -pub const R_TILEPRO_IMM16_X0_HA: u32 = 29; -/// X1 pipe high 16-bit, adjusted -pub const R_TILEPRO_IMM16_X1_HA: u32 = 30; -/// X0 pipe PC relative 16 bit -pub const R_TILEPRO_IMM16_X0_PCREL: u32 = 31; -/// X1 pipe PC relative 16 bit -pub const R_TILEPRO_IMM16_X1_PCREL: u32 = 32; -/// X0 pipe PC relative low 16 bit -pub const R_TILEPRO_IMM16_X0_LO_PCREL: u32 = 33; -/// X1 pipe PC relative low 16 bit -pub const R_TILEPRO_IMM16_X1_LO_PCREL: u32 = 34; -/// X0 pipe PC relative high 16 bit -pub const R_TILEPRO_IMM16_X0_HI_PCREL: u32 = 35; -/// X1 pipe PC relative high 16 bit -pub const R_TILEPRO_IMM16_X1_HI_PCREL: u32 = 36; -/// X0 pipe PC relative ha() 16 bit -pub const R_TILEPRO_IMM16_X0_HA_PCREL: u32 = 37; -/// X1 pipe PC relative ha() 16 bit -pub const R_TILEPRO_IMM16_X1_HA_PCREL: u32 = 38; -/// X0 pipe 16-bit GOT offset -pub const R_TILEPRO_IMM16_X0_GOT: u32 = 39; -/// X1 pipe 16-bit GOT offset -pub const R_TILEPRO_IMM16_X1_GOT: u32 = 40; -/// X0 pipe low 16-bit GOT offset -pub const R_TILEPRO_IMM16_X0_GOT_LO: u32 = 41; -/// X1 pipe low 16-bit GOT offset -pub const R_TILEPRO_IMM16_X1_GOT_LO: u32 = 42; -/// X0 pipe high 16-bit GOT offset -pub const R_TILEPRO_IMM16_X0_GOT_HI: u32 = 43; -/// X1 pipe high 16-bit GOT offset -pub const R_TILEPRO_IMM16_X1_GOT_HI: u32 = 44; -/// X0 pipe ha() 16-bit GOT offset -pub const R_TILEPRO_IMM16_X0_GOT_HA: u32 = 45; -/// X1 pipe ha() 16-bit GOT offset -pub const R_TILEPRO_IMM16_X1_GOT_HA: u32 = 46; -/// X0 pipe mm "start" -pub const R_TILEPRO_MMSTART_X0: u32 = 47; -/// X0 pipe mm "end" -pub const R_TILEPRO_MMEND_X0: u32 = 48; -/// X1 pipe mm "start" -pub const R_TILEPRO_MMSTART_X1: u32 = 49; -/// X1 pipe mm "end" -pub const R_TILEPRO_MMEND_X1: u32 = 50; -/// X0 pipe shift amount -pub const R_TILEPRO_SHAMT_X0: u32 = 51; -/// X1 pipe shift amount -pub const R_TILEPRO_SHAMT_X1: u32 = 52; -/// Y0 pipe shift amount -pub const R_TILEPRO_SHAMT_Y0: u32 = 53; -/// Y1 pipe shift amount -pub const R_TILEPRO_SHAMT_Y1: u32 = 54; -/// X1 pipe destination 8-bit -pub const R_TILEPRO_DEST_IMM8_X1: u32 = 55; -// Relocs 56-59 are currently not defined. -/// "jal" for TLS GD -pub const R_TILEPRO_TLS_GD_CALL: u32 = 60; -/// X0 pipe "addi" for TLS GD -pub const R_TILEPRO_IMM8_X0_TLS_GD_ADD: u32 = 61; -/// X1 pipe "addi" for TLS GD -pub const R_TILEPRO_IMM8_X1_TLS_GD_ADD: u32 = 62; -/// Y0 pipe "addi" for TLS GD -pub const R_TILEPRO_IMM8_Y0_TLS_GD_ADD: u32 = 63; -/// Y1 pipe "addi" for TLS GD -pub const R_TILEPRO_IMM8_Y1_TLS_GD_ADD: u32 = 64; -/// "lw_tls" for TLS IE -pub const R_TILEPRO_TLS_IE_LOAD: u32 = 65; -/// X0 pipe 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X0_TLS_GD: u32 = 66; -/// X1 pipe 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X1_TLS_GD: u32 = 67; -/// X0 pipe low 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X0_TLS_GD_LO: u32 = 68; -/// X1 pipe low 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X1_TLS_GD_LO: u32 = 69; -/// X0 pipe high 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X0_TLS_GD_HI: u32 = 70; -/// X1 pipe high 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X1_TLS_GD_HI: u32 = 71; -/// X0 pipe ha() 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X0_TLS_GD_HA: u32 = 72; -/// X1 pipe ha() 16-bit TLS GD offset -pub const R_TILEPRO_IMM16_X1_TLS_GD_HA: u32 = 73; -/// X0 pipe 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X0_TLS_IE: u32 = 74; -/// X1 pipe 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X1_TLS_IE: u32 = 75; -/// X0 pipe low 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X0_TLS_IE_LO: u32 = 76; -/// X1 pipe low 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X1_TLS_IE_LO: u32 = 77; -/// X0 pipe high 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X0_TLS_IE_HI: u32 = 78; -/// X1 pipe high 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X1_TLS_IE_HI: u32 = 79; -/// X0 pipe ha() 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X0_TLS_IE_HA: u32 = 80; -/// X1 pipe ha() 16-bit TLS IE offset -pub const R_TILEPRO_IMM16_X1_TLS_IE_HA: u32 = 81; -/// ID of module containing symbol -pub const R_TILEPRO_TLS_DTPMOD32: u32 = 82; -/// Offset in TLS block -pub const R_TILEPRO_TLS_DTPOFF32: u32 = 83; -/// Offset in static TLS block -pub const R_TILEPRO_TLS_TPOFF32: u32 = 84; -/// X0 pipe 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X0_TLS_LE: u32 = 85; -/// X1 pipe 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X1_TLS_LE: u32 = 86; -/// X0 pipe low 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X0_TLS_LE_LO: u32 = 87; -/// X1 pipe low 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X1_TLS_LE_LO: u32 = 88; -/// X0 pipe high 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X0_TLS_LE_HI: u32 = 89; -/// X1 pipe high 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X1_TLS_LE_HI: u32 = 90; -/// X0 pipe ha() 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X0_TLS_LE_HA: u32 = 91; -/// X1 pipe ha() 16-bit TLS LE offset -pub const R_TILEPRO_IMM16_X1_TLS_LE_HA: u32 = 92; - -/// GNU C++ vtable hierarchy -pub const R_TILEPRO_GNU_VTINHERIT: u32 = 128; -/// GNU C++ vtable member usage -pub const R_TILEPRO_GNU_VTENTRY: u32 = 129; - -// TILE-Gx values `Rel*::r_type`. -/// No reloc -pub const R_TILEGX_NONE: u32 = 0; -/// Direct 64 bit -pub const R_TILEGX_64: u32 = 1; -/// Direct 32 bit -pub const R_TILEGX_32: u32 = 2; -/// Direct 16 bit -pub const R_TILEGX_16: u32 = 3; -/// Direct 8 bit -pub const R_TILEGX_8: u32 = 4; -/// PC relative 64 bit -pub const R_TILEGX_64_PCREL: u32 = 5; -/// PC relative 32 bit -pub const R_TILEGX_32_PCREL: u32 = 6; -/// PC relative 16 bit -pub const R_TILEGX_16_PCREL: u32 = 7; -/// PC relative 8 bit -pub const R_TILEGX_8_PCREL: u32 = 8; -/// hword 0 16-bit -pub const R_TILEGX_HW0: u32 = 9; -/// hword 1 16-bit -pub const R_TILEGX_HW1: u32 = 10; -/// hword 2 16-bit -pub const R_TILEGX_HW2: u32 = 11; -/// hword 3 16-bit -pub const R_TILEGX_HW3: u32 = 12; -/// last hword 0 16-bit -pub const R_TILEGX_HW0_LAST: u32 = 13; -/// last hword 1 16-bit -pub const R_TILEGX_HW1_LAST: u32 = 14; -/// last hword 2 16-bit -pub const R_TILEGX_HW2_LAST: u32 = 15; -/// Copy relocation -pub const R_TILEGX_COPY: u32 = 16; -/// Create GOT entry -pub const R_TILEGX_GLOB_DAT: u32 = 17; -/// Create PLT entry -pub const R_TILEGX_JMP_SLOT: u32 = 18; -/// Adjust by program base -pub const R_TILEGX_RELATIVE: u32 = 19; -/// X1 pipe branch offset -pub const R_TILEGX_BROFF_X1: u32 = 20; -/// X1 pipe jump offset -pub const R_TILEGX_JUMPOFF_X1: u32 = 21; -/// X1 pipe jump offset to PLT -pub const R_TILEGX_JUMPOFF_X1_PLT: u32 = 22; -/// X0 pipe 8-bit -pub const R_TILEGX_IMM8_X0: u32 = 23; -/// Y0 pipe 8-bit -pub const R_TILEGX_IMM8_Y0: u32 = 24; -/// X1 pipe 8-bit -pub const R_TILEGX_IMM8_X1: u32 = 25; -/// Y1 pipe 8-bit -pub const R_TILEGX_IMM8_Y1: u32 = 26; -/// X1 pipe destination 8-bit -pub const R_TILEGX_DEST_IMM8_X1: u32 = 27; -/// X1 pipe mtspr -pub const R_TILEGX_MT_IMM14_X1: u32 = 28; -/// X1 pipe mfspr -pub const R_TILEGX_MF_IMM14_X1: u32 = 29; -/// X0 pipe mm "start" -pub const R_TILEGX_MMSTART_X0: u32 = 30; -/// X0 pipe mm "end" -pub const R_TILEGX_MMEND_X0: u32 = 31; -/// X0 pipe shift amount -pub const R_TILEGX_SHAMT_X0: u32 = 32; -/// X1 pipe shift amount -pub const R_TILEGX_SHAMT_X1: u32 = 33; -/// Y0 pipe shift amount -pub const R_TILEGX_SHAMT_Y0: u32 = 34; -/// Y1 pipe shift amount -pub const R_TILEGX_SHAMT_Y1: u32 = 35; -/// X0 pipe hword 0 -pub const R_TILEGX_IMM16_X0_HW0: u32 = 36; -/// X1 pipe hword 0 -pub const R_TILEGX_IMM16_X1_HW0: u32 = 37; -/// X0 pipe hword 1 -pub const R_TILEGX_IMM16_X0_HW1: u32 = 38; -/// X1 pipe hword 1 -pub const R_TILEGX_IMM16_X1_HW1: u32 = 39; -/// X0 pipe hword 2 -pub const R_TILEGX_IMM16_X0_HW2: u32 = 40; -/// X1 pipe hword 2 -pub const R_TILEGX_IMM16_X1_HW2: u32 = 41; -/// X0 pipe hword 3 -pub const R_TILEGX_IMM16_X0_HW3: u32 = 42; -/// X1 pipe hword 3 -pub const R_TILEGX_IMM16_X1_HW3: u32 = 43; -/// X0 pipe last hword 0 -pub const R_TILEGX_IMM16_X0_HW0_LAST: u32 = 44; -/// X1 pipe last hword 0 -pub const R_TILEGX_IMM16_X1_HW0_LAST: u32 = 45; -/// X0 pipe last hword 1 -pub const R_TILEGX_IMM16_X0_HW1_LAST: u32 = 46; -/// X1 pipe last hword 1 -pub const R_TILEGX_IMM16_X1_HW1_LAST: u32 = 47; -/// X0 pipe last hword 2 -pub const R_TILEGX_IMM16_X0_HW2_LAST: u32 = 48; -/// X1 pipe last hword 2 -pub const R_TILEGX_IMM16_X1_HW2_LAST: u32 = 49; -/// X0 pipe PC relative hword 0 -pub const R_TILEGX_IMM16_X0_HW0_PCREL: u32 = 50; -/// X1 pipe PC relative hword 0 -pub const R_TILEGX_IMM16_X1_HW0_PCREL: u32 = 51; -/// X0 pipe PC relative hword 1 -pub const R_TILEGX_IMM16_X0_HW1_PCREL: u32 = 52; -/// X1 pipe PC relative hword 1 -pub const R_TILEGX_IMM16_X1_HW1_PCREL: u32 = 53; -/// X0 pipe PC relative hword 2 -pub const R_TILEGX_IMM16_X0_HW2_PCREL: u32 = 54; -/// X1 pipe PC relative hword 2 -pub const R_TILEGX_IMM16_X1_HW2_PCREL: u32 = 55; -/// X0 pipe PC relative hword 3 -pub const R_TILEGX_IMM16_X0_HW3_PCREL: u32 = 56; -/// X1 pipe PC relative hword 3 -pub const R_TILEGX_IMM16_X1_HW3_PCREL: u32 = 57; -/// X0 pipe PC-rel last hword 0 -pub const R_TILEGX_IMM16_X0_HW0_LAST_PCREL: u32 = 58; -/// X1 pipe PC-rel last hword 0 -pub const R_TILEGX_IMM16_X1_HW0_LAST_PCREL: u32 = 59; -/// X0 pipe PC-rel last hword 1 -pub const R_TILEGX_IMM16_X0_HW1_LAST_PCREL: u32 = 60; -/// X1 pipe PC-rel last hword 1 -pub const R_TILEGX_IMM16_X1_HW1_LAST_PCREL: u32 = 61; -/// X0 pipe PC-rel last hword 2 -pub const R_TILEGX_IMM16_X0_HW2_LAST_PCREL: u32 = 62; -/// X1 pipe PC-rel last hword 2 -pub const R_TILEGX_IMM16_X1_HW2_LAST_PCREL: u32 = 63; -/// X0 pipe hword 0 GOT offset -pub const R_TILEGX_IMM16_X0_HW0_GOT: u32 = 64; -/// X1 pipe hword 0 GOT offset -pub const R_TILEGX_IMM16_X1_HW0_GOT: u32 = 65; -/// X0 pipe PC-rel PLT hword 0 -pub const R_TILEGX_IMM16_X0_HW0_PLT_PCREL: u32 = 66; -/// X1 pipe PC-rel PLT hword 0 -pub const R_TILEGX_IMM16_X1_HW0_PLT_PCREL: u32 = 67; -/// X0 pipe PC-rel PLT hword 1 -pub const R_TILEGX_IMM16_X0_HW1_PLT_PCREL: u32 = 68; -/// X1 pipe PC-rel PLT hword 1 -pub const R_TILEGX_IMM16_X1_HW1_PLT_PCREL: u32 = 69; -/// X0 pipe PC-rel PLT hword 2 -pub const R_TILEGX_IMM16_X0_HW2_PLT_PCREL: u32 = 70; -/// X1 pipe PC-rel PLT hword 2 -pub const R_TILEGX_IMM16_X1_HW2_PLT_PCREL: u32 = 71; -/// X0 pipe last hword 0 GOT offset -pub const R_TILEGX_IMM16_X0_HW0_LAST_GOT: u32 = 72; -/// X1 pipe last hword 0 GOT offset -pub const R_TILEGX_IMM16_X1_HW0_LAST_GOT: u32 = 73; -/// X0 pipe last hword 1 GOT offset -pub const R_TILEGX_IMM16_X0_HW1_LAST_GOT: u32 = 74; -/// X1 pipe last hword 1 GOT offset -pub const R_TILEGX_IMM16_X1_HW1_LAST_GOT: u32 = 75; -/// X0 pipe PC-rel PLT hword 3 -pub const R_TILEGX_IMM16_X0_HW3_PLT_PCREL: u32 = 76; -/// X1 pipe PC-rel PLT hword 3 -pub const R_TILEGX_IMM16_X1_HW3_PLT_PCREL: u32 = 77; -/// X0 pipe hword 0 TLS GD offset -pub const R_TILEGX_IMM16_X0_HW0_TLS_GD: u32 = 78; -/// X1 pipe hword 0 TLS GD offset -pub const R_TILEGX_IMM16_X1_HW0_TLS_GD: u32 = 79; -/// X0 pipe hword 0 TLS LE offset -pub const R_TILEGX_IMM16_X0_HW0_TLS_LE: u32 = 80; -/// X1 pipe hword 0 TLS LE offset -pub const R_TILEGX_IMM16_X1_HW0_TLS_LE: u32 = 81; -/// X0 pipe last hword 0 LE off -pub const R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE: u32 = 82; -/// X1 pipe last hword 0 LE off -pub const R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE: u32 = 83; -/// X0 pipe last hword 1 LE off -pub const R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE: u32 = 84; -/// X1 pipe last hword 1 LE off -pub const R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE: u32 = 85; -/// X0 pipe last hword 0 GD off -pub const R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD: u32 = 86; -/// X1 pipe last hword 0 GD off -pub const R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD: u32 = 87; -/// X0 pipe last hword 1 GD off -pub const R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD: u32 = 88; -/// X1 pipe last hword 1 GD off -pub const R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD: u32 = 89; -// Relocs 90-91 are currently not defined. -/// X0 pipe hword 0 TLS IE offset -pub const R_TILEGX_IMM16_X0_HW0_TLS_IE: u32 = 92; -/// X1 pipe hword 0 TLS IE offset -pub const R_TILEGX_IMM16_X1_HW0_TLS_IE: u32 = 93; -/// X0 pipe PC-rel PLT last hword 0 -pub const R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL: u32 = 94; -/// X1 pipe PC-rel PLT last hword 0 -pub const R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL: u32 = 95; -/// X0 pipe PC-rel PLT last hword 1 -pub const R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL: u32 = 96; -/// X1 pipe PC-rel PLT last hword 1 -pub const R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL: u32 = 97; -/// X0 pipe PC-rel PLT last hword 2 -pub const R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL: u32 = 98; -/// X1 pipe PC-rel PLT last hword 2 -pub const R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL: u32 = 99; -/// X0 pipe last hword 0 IE off -pub const R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE: u32 = 100; -/// X1 pipe last hword 0 IE off -pub const R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE: u32 = 101; -/// X0 pipe last hword 1 IE off -pub const R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE: u32 = 102; -/// X1 pipe last hword 1 IE off -pub const R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE: u32 = 103; -// Relocs 104-105 are currently not defined. -/// 64-bit ID of symbol's module -pub const R_TILEGX_TLS_DTPMOD64: u32 = 106; -/// 64-bit offset in TLS block -pub const R_TILEGX_TLS_DTPOFF64: u32 = 107; -/// 64-bit offset in static TLS block -pub const R_TILEGX_TLS_TPOFF64: u32 = 108; -/// 32-bit ID of symbol's module -pub const R_TILEGX_TLS_DTPMOD32: u32 = 109; -/// 32-bit offset in TLS block -pub const R_TILEGX_TLS_DTPOFF32: u32 = 110; -/// 32-bit offset in static TLS block -pub const R_TILEGX_TLS_TPOFF32: u32 = 111; -/// "jal" for TLS GD -pub const R_TILEGX_TLS_GD_CALL: u32 = 112; -/// X0 pipe "addi" for TLS GD -pub const R_TILEGX_IMM8_X0_TLS_GD_ADD: u32 = 113; -/// X1 pipe "addi" for TLS GD -pub const R_TILEGX_IMM8_X1_TLS_GD_ADD: u32 = 114; -/// Y0 pipe "addi" for TLS GD -pub const R_TILEGX_IMM8_Y0_TLS_GD_ADD: u32 = 115; -/// Y1 pipe "addi" for TLS GD -pub const R_TILEGX_IMM8_Y1_TLS_GD_ADD: u32 = 116; -/// "ld_tls" for TLS IE -pub const R_TILEGX_TLS_IE_LOAD: u32 = 117; -/// X0 pipe "addi" for TLS GD/IE -pub const R_TILEGX_IMM8_X0_TLS_ADD: u32 = 118; -/// X1 pipe "addi" for TLS GD/IE -pub const R_TILEGX_IMM8_X1_TLS_ADD: u32 = 119; -/// Y0 pipe "addi" for TLS GD/IE -pub const R_TILEGX_IMM8_Y0_TLS_ADD: u32 = 120; -/// Y1 pipe "addi" for TLS GD/IE -pub const R_TILEGX_IMM8_Y1_TLS_ADD: u32 = 121; - -/// GNU C++ vtable hierarchy -pub const R_TILEGX_GNU_VTINHERIT: u32 = 128; -/// GNU C++ vtable member usage -pub const R_TILEGX_GNU_VTENTRY: u32 = 129; - -// RISC-V values `FileHeader*::e_flags`. -pub const EF_RISCV_RVC: u32 = 0x0001; -pub const EF_RISCV_FLOAT_ABI: u32 = 0x0006; -pub const EF_RISCV_FLOAT_ABI_SOFT: u32 = 0x0000; -pub const EF_RISCV_FLOAT_ABI_SINGLE: u32 = 0x0002; -pub const EF_RISCV_FLOAT_ABI_DOUBLE: u32 = 0x0004; -pub const EF_RISCV_FLOAT_ABI_QUAD: u32 = 0x0006; -pub const EF_RISCV_RVE: u32 = 0x0008; -pub const EF_RISCV_TSO: u32 = 0x0010; - -// RISC-V values `Rel*::r_type`. -pub const R_RISCV_NONE: u32 = 0; -pub const R_RISCV_32: u32 = 1; -pub const R_RISCV_64: u32 = 2; -pub const R_RISCV_RELATIVE: u32 = 3; -pub const R_RISCV_COPY: u32 = 4; -pub const R_RISCV_JUMP_SLOT: u32 = 5; -pub const R_RISCV_TLS_DTPMOD32: u32 = 6; -pub const R_RISCV_TLS_DTPMOD64: u32 = 7; -pub const R_RISCV_TLS_DTPREL32: u32 = 8; -pub const R_RISCV_TLS_DTPREL64: u32 = 9; -pub const R_RISCV_TLS_TPREL32: u32 = 10; -pub const R_RISCV_TLS_TPREL64: u32 = 11; -pub const R_RISCV_BRANCH: u32 = 16; -pub const R_RISCV_JAL: u32 = 17; -pub const R_RISCV_CALL: u32 = 18; -pub const R_RISCV_CALL_PLT: u32 = 19; -pub const R_RISCV_GOT_HI20: u32 = 20; -pub const R_RISCV_TLS_GOT_HI20: u32 = 21; -pub const R_RISCV_TLS_GD_HI20: u32 = 22; -pub const R_RISCV_PCREL_HI20: u32 = 23; -pub const R_RISCV_PCREL_LO12_I: u32 = 24; -pub const R_RISCV_PCREL_LO12_S: u32 = 25; -pub const R_RISCV_HI20: u32 = 26; -pub const R_RISCV_LO12_I: u32 = 27; -pub const R_RISCV_LO12_S: u32 = 28; -pub const R_RISCV_TPREL_HI20: u32 = 29; -pub const R_RISCV_TPREL_LO12_I: u32 = 30; -pub const R_RISCV_TPREL_LO12_S: u32 = 31; -pub const R_RISCV_TPREL_ADD: u32 = 32; -pub const R_RISCV_ADD8: u32 = 33; -pub const R_RISCV_ADD16: u32 = 34; -pub const R_RISCV_ADD32: u32 = 35; -pub const R_RISCV_ADD64: u32 = 36; -pub const R_RISCV_SUB8: u32 = 37; -pub const R_RISCV_SUB16: u32 = 38; -pub const R_RISCV_SUB32: u32 = 39; -pub const R_RISCV_SUB64: u32 = 40; -pub const R_RISCV_GNU_VTINHERIT: u32 = 41; -pub const R_RISCV_GNU_VTENTRY: u32 = 42; -pub const R_RISCV_ALIGN: u32 = 43; -pub const R_RISCV_RVC_BRANCH: u32 = 44; -pub const R_RISCV_RVC_JUMP: u32 = 45; -pub const R_RISCV_RVC_LUI: u32 = 46; -pub const R_RISCV_GPREL_I: u32 = 47; -pub const R_RISCV_GPREL_S: u32 = 48; -pub const R_RISCV_TPREL_I: u32 = 49; -pub const R_RISCV_TPREL_S: u32 = 50; -pub const R_RISCV_RELAX: u32 = 51; -pub const R_RISCV_SUB6: u32 = 52; -pub const R_RISCV_SET6: u32 = 53; -pub const R_RISCV_SET8: u32 = 54; -pub const R_RISCV_SET16: u32 = 55; -pub const R_RISCV_SET32: u32 = 56; -pub const R_RISCV_32_PCREL: u32 = 57; - -// BPF values `Rel*::r_type`. -/// No reloc -pub const R_BPF_NONE: u32 = 0; -pub const R_BPF_64_64: u32 = 1; -pub const R_BPF_64_32: u32 = 10; - -// SBF values `Rel*::r_type`. -/// No reloc -pub const R_SBF_NONE: u32 = 0; -pub const R_SBF_64_64: u32 = 1; -pub const R_SBF_64_32: u32 = 10; - -// Imagination Meta values `Rel*::r_type`. - -pub const R_METAG_HIADDR16: u32 = 0; -pub const R_METAG_LOADDR16: u32 = 1; -/// 32bit absolute address -pub const R_METAG_ADDR32: u32 = 2; -/// No reloc -pub const R_METAG_NONE: u32 = 3; -pub const R_METAG_RELBRANCH: u32 = 4; -pub const R_METAG_GETSETOFF: u32 = 5; - -// Backward compatibility -pub const R_METAG_REG32OP1: u32 = 6; -pub const R_METAG_REG32OP2: u32 = 7; -pub const R_METAG_REG32OP3: u32 = 8; -pub const R_METAG_REG16OP1: u32 = 9; -pub const R_METAG_REG16OP2: u32 = 10; -pub const R_METAG_REG16OP3: u32 = 11; -pub const R_METAG_REG32OP4: u32 = 12; - -pub const R_METAG_HIOG: u32 = 13; -pub const R_METAG_LOOG: u32 = 14; - -pub const R_METAG_REL8: u32 = 15; -pub const R_METAG_REL16: u32 = 16; - -pub const R_METAG_GNU_VTINHERIT: u32 = 30; -pub const R_METAG_GNU_VTENTRY: u32 = 31; - -// PIC relocations -pub const R_METAG_HI16_GOTOFF: u32 = 32; -pub const R_METAG_LO16_GOTOFF: u32 = 33; -pub const R_METAG_GETSET_GOTOFF: u32 = 34; -pub const R_METAG_GETSET_GOT: u32 = 35; -pub const R_METAG_HI16_GOTPC: u32 = 36; -pub const R_METAG_LO16_GOTPC: u32 = 37; -pub const R_METAG_HI16_PLT: u32 = 38; -pub const R_METAG_LO16_PLT: u32 = 39; -pub const R_METAG_RELBRANCH_PLT: u32 = 40; -pub const R_METAG_GOTOFF: u32 = 41; -pub const R_METAG_PLT: u32 = 42; -pub const R_METAG_COPY: u32 = 43; -pub const R_METAG_JMP_SLOT: u32 = 44; -pub const R_METAG_RELATIVE: u32 = 45; -pub const R_METAG_GLOB_DAT: u32 = 46; - -// TLS relocations -pub const R_METAG_TLS_GD: u32 = 47; -pub const R_METAG_TLS_LDM: u32 = 48; -pub const R_METAG_TLS_LDO_HI16: u32 = 49; -pub const R_METAG_TLS_LDO_LO16: u32 = 50; -pub const R_METAG_TLS_LDO: u32 = 51; -pub const R_METAG_TLS_IE: u32 = 52; -pub const R_METAG_TLS_IENONPIC: u32 = 53; -pub const R_METAG_TLS_IENONPIC_HI16: u32 = 54; -pub const R_METAG_TLS_IENONPIC_LO16: u32 = 55; -pub const R_METAG_TLS_TPOFF: u32 = 56; -pub const R_METAG_TLS_DTPMOD: u32 = 57; -pub const R_METAG_TLS_DTPOFF: u32 = 58; -pub const R_METAG_TLS_LE: u32 = 59; -pub const R_METAG_TLS_LE_HI16: u32 = 60; -pub const R_METAG_TLS_LE_LO16: u32 = 61; - -// NDS32 values `Rel*::r_type`. -pub const R_NDS32_NONE: u32 = 0; -pub const R_NDS32_32_RELA: u32 = 20; -pub const R_NDS32_COPY: u32 = 39; -pub const R_NDS32_GLOB_DAT: u32 = 40; -pub const R_NDS32_JMP_SLOT: u32 = 41; -pub const R_NDS32_RELATIVE: u32 = 42; -pub const R_NDS32_TLS_TPOFF: u32 = 102; -pub const R_NDS32_TLS_DESC: u32 = 119; - -// LoongArch values `FileHeader*::e_flags`. -/// Additional properties of the base ABI type, including the FP calling -/// convention. -pub const EF_LARCH_ABI_MODIFIER_MASK: u32 = 0x7; -/// Uses GPRs and the stack for parameter passing -pub const EF_LARCH_ABI_SOFT_FLOAT: u32 = 0x1; -/// Uses GPRs, 32-bit FPRs and the stack for parameter passing -pub const EF_LARCH_ABI_SINGLE_FLOAT: u32 = 0x2; -/// Uses GPRs, 64-bit FPRs and the stack for parameter passing -pub const EF_LARCH_ABI_DOUBLE_FLOAT: u32 = 0x3; -/// Uses relocation types directly writing to immediate slots -pub const EF_LARCH_OBJABI_V1: u32 = 0x40; - -// LoongArch values `Rel*::r_type`. -/// No reloc -pub const R_LARCH_NONE: u32 = 0; -/// Runtime address resolving -pub const R_LARCH_32: u32 = 1; -/// Runtime address resolving -pub const R_LARCH_64: u32 = 2; -/// Runtime fixup for load-address -pub const R_LARCH_RELATIVE: u32 = 3; -/// Runtime memory copy in executable -pub const R_LARCH_COPY: u32 = 4; -/// Runtime PLT supporting -pub const R_LARCH_JUMP_SLOT: u32 = 5; -/// Runtime relocation for TLS-GD -pub const R_LARCH_TLS_DTPMOD32: u32 = 6; -/// Runtime relocation for TLS-GD -pub const R_LARCH_TLS_DTPMOD64: u32 = 7; -/// Runtime relocation for TLS-GD -pub const R_LARCH_TLS_DTPREL32: u32 = 8; -/// Runtime relocation for TLS-GD -pub const R_LARCH_TLS_DTPREL64: u32 = 9; -/// Runtime relocation for TLE-IE -pub const R_LARCH_TLS_TPREL32: u32 = 10; -/// Runtime relocation for TLE-IE -pub const R_LARCH_TLS_TPREL64: u32 = 11; -/// Runtime local indirect function resolving -pub const R_LARCH_IRELATIVE: u32 = 12; -/// Mark la.abs: load absolute address for static link. -pub const R_LARCH_MARK_LA: u32 = 20; -/// Mark external label branch: access PC relative address for static link. -pub const R_LARCH_MARK_PCREL: u32 = 21; -/// Push PC-relative offset -pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; -/// Push constant or absolute address -pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; -/// Duplicate stack top -pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; -/// Push for access GOT entry -pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; -/// Push for TLS-LE -pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; -/// Push for TLS-IE -pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; -/// Push for TLS-GD -pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; -/// Push for external function calling -pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; -/// Assert stack top -pub const R_LARCH_SOP_ASSERT: u32 = 30; -/// Stack top logical not (unary) -pub const R_LARCH_SOP_NOT: u32 = 31; -/// Stack top subtraction (binary) -pub const R_LARCH_SOP_SUB: u32 = 32; -/// Stack top left shift (binary) -pub const R_LARCH_SOP_SL: u32 = 33; -/// Stack top right shift (binary) -pub const R_LARCH_SOP_SR: u32 = 34; -/// Stack top addition (binary) -pub const R_LARCH_SOP_ADD: u32 = 35; -/// Stack top bitwise and (binary) -pub const R_LARCH_SOP_AND: u32 = 36; -/// Stack top selection (tertiary) -pub const R_LARCH_SOP_IF_ELSE: u32 = 37; -/// Pop stack top to fill 5-bit signed immediate operand -pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; -/// Pop stack top to fill 12-bit unsigned immediate operand -pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; -/// Pop stack top to fill 12-bit signed immediate operand -pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; -/// Pop stack top to fill 16-bit signed immediate operand -pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; -/// Pop stack top to fill 18-bit signed immediate operand with two trailing -/// zeros implied -pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; -/// Pop stack top to fill 20-bit signed immediate operand -pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; -/// Pop stack top to fill 23-bit signed immediate operand with two trailing -/// zeros implied -pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; -/// Pop stack top to fill 28-bit signed immediate operand with two trailing -/// zeros implied -pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; -/// Pop stack top to fill an instruction -pub const R_LARCH_SOP_POP_32_U: u32 = 46; -/// 8-bit in-place addition -pub const R_LARCH_ADD8: u32 = 47; -/// 16-bit in-place addition -pub const R_LARCH_ADD16: u32 = 48; -/// 24-bit in-place addition -pub const R_LARCH_ADD24: u32 = 49; -/// 32-bit in-place addition -pub const R_LARCH_ADD32: u32 = 50; -/// 64-bit in-place addition -pub const R_LARCH_ADD64: u32 = 51; -/// 8-bit in-place subtraction -pub const R_LARCH_SUB8: u32 = 52; -/// 16-bit in-place subtraction -pub const R_LARCH_SUB16: u32 = 53; -/// 24-bit in-place subtraction -pub const R_LARCH_SUB24: u32 = 54; -/// 32-bit in-place subtraction -pub const R_LARCH_SUB32: u32 = 55; -/// 64-bit in-place subtraction -pub const R_LARCH_SUB64: u32 = 56; -/// GNU C++ vtable hierarchy -pub const R_LARCH_GNU_VTINHERIT: u32 = 57; -/// GNU C++ vtable member usage -pub const R_LARCH_GNU_VTENTRY: u32 = 58; -/// 18-bit PC-relative jump offset with two trailing zeros -pub const R_LARCH_B16: u32 = 64; -/// 23-bit PC-relative jump offset with two trailing zeros -pub const R_LARCH_B21: u32 = 65; -/// 28-bit PC-relative jump offset with two trailing zeros -pub const R_LARCH_B26: u32 = 66; -/// 12..=31 bits of 32/64-bit absolute address -pub const R_LARCH_ABS_HI20: u32 = 67; -/// 0..=11 bits of 32/64-bit absolute address -pub const R_LARCH_ABS_LO12: u32 = 68; -/// 32..=51 bits of 64-bit absolute address -pub const R_LARCH_ABS64_LO20: u32 = 69; -/// 52..=63 bits of 64-bit absolute address -pub const R_LARCH_ABS64_HI12: u32 = 70; -/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to -/// `(S + A + 0x800) & 0xfffff000`, with 12 trailing zeros removed. -/// -/// We define the *PC relative anchor* for `S + A` as `PC + offs` (`offs` -/// is sign-extended to VA bits). -pub const R_LARCH_PCALA_HI20: u32 = 71; -/// Same as R_LARCH_ABS_LO12. 0..=11 bits of the 32/64-bit offset from the -/// [PC relative anchor][R_LARCH_PCALA_HI20]. -pub const R_LARCH_PCALA_LO12: u32 = 72; -/// 32..=51 bits of the 64-bit offset from the -/// [PC relative anchor][R_LARCH_PCALA_HI20]. -pub const R_LARCH_PCALA64_LO20: u32 = 73; -/// 52..=63 bits of the 64-bit offset from the -/// [PC relative anchor][R_LARCH_PCALA_HI20]. -pub const R_LARCH_PCALA64_HI12: u32 = 74; -/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to -/// `(GP + G + 0x800) & 0xfffff000`, with 12 trailing zeros removed. -/// -/// We define the *PC relative anchor* for the GOT entry at `GP + G` as -/// `PC + offs` (`offs` is sign-extended to VA bits). -pub const R_LARCH_GOT_PC_HI20: u32 = 75; -/// 0..=11 bits of the 32/64-bit offset from the -/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry. -pub const R_LARCH_GOT_PC_LO12: u32 = 76; -/// 32..=51 bits of the 64-bit offset from the -/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry. -pub const R_LARCH_GOT64_PC_LO20: u32 = 77; -/// 52..=63 bits of the 64-bit offset from the -/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry. -pub const R_LARCH_GOT64_PC_HI12: u32 = 78; -/// 12..=31 bits of 32/64-bit GOT entry absolute address -pub const R_LARCH_GOT_HI20: u32 = 79; -/// 0..=11 bits of 32/64-bit GOT entry absolute address -pub const R_LARCH_GOT_LO12: u32 = 80; -/// 32..=51 bits of 64-bit GOT entry absolute address -pub const R_LARCH_GOT64_LO20: u32 = 81; -/// 52..=63 bits of 64-bit GOT entry absolute address -pub const R_LARCH_GOT64_HI12: u32 = 82; -/// 12..=31 bits of TLS LE 32/64-bit offset from thread pointer -pub const R_LARCH_TLS_LE_HI20: u32 = 83; -/// 0..=11 bits of TLS LE 32/64-bit offset from thread pointer -pub const R_LARCH_TLS_LE_LO12: u32 = 84; -/// 32..=51 bits of TLS LE 64-bit offset from thread pointer -pub const R_LARCH_TLS_LE64_LO20: u32 = 85; -/// 52..=63 bits of TLS LE 64-bit offset from thread pointer -pub const R_LARCH_TLS_LE64_HI12: u32 = 86; -/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to -/// `(GP + IE + 0x800) & 0xfffff000`, with 12 trailing zeros removed. -/// -/// We define the *PC relative anchor* for the TLS IE GOT entry at -/// `GP + IE` as `PC + offs` (`offs` is sign-extended to VA bits). -pub const R_LARCH_TLS_IE_PC_HI20: u32 = 87; -/// 0..=12 bits of the 32/64-bit offset from the -/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry. -pub const R_LARCH_TLS_IE_PC_LO12: u32 = 88; -/// 32..=51 bits of the 64-bit offset from the -/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry. -pub const R_LARCH_TLS_IE64_PC_LO20: u32 = 89; -/// 52..=63 bits of the 64-bit offset from the -/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry. -pub const R_LARCH_TLS_IE64_PC_HI12: u32 = 90; -/// 12..=31 bits of TLS IE GOT entry 32/64-bit absolute address -pub const R_LARCH_TLS_IE_HI20: u32 = 91; -/// 0..=11 bits of TLS IE GOT entry 32/64-bit absolute address -pub const R_LARCH_TLS_IE_LO12: u32 = 92; -/// 32..=51 bits of TLS IE GOT entry 64-bit absolute address -pub const R_LARCH_TLS_IE64_LO20: u32 = 93; -/// 51..=63 bits of TLS IE GOT entry 64-bit absolute address -pub const R_LARCH_TLS_IE64_HI12: u32 = 94; -/// 12..=31 bits of the offset from `PC` to `GP + GD + 0x800`, where -/// `GP + GD` is a TLS LD GOT entry -pub const R_LARCH_TLS_LD_PC_HI20: u32 = 95; -/// 12..=31 bits of TLS LD GOT entry 32/64-bit absolute address -pub const R_LARCH_TLS_LD_HI20: u32 = 96; -/// 12..=31 bits of the 32/64-bit PC-relative offset to the PC-relative -/// anchor for the TLE GD GOT entry. -pub const R_LARCH_TLS_GD_PC_HI20: u32 = 97; -/// 12..=31 bits of TLS GD GOT entry 32/64-bit absolute address -pub const R_LARCH_TLS_GD_HI20: u32 = 98; -/// 32-bit PC relative -pub const R_LARCH_32_PCREL: u32 = 99; -/// Paired with a normal relocation at the same address to indicate the -/// instruction can be relaxed -pub const R_LARCH_RELAX: u32 = 100; -/// Reserved -pub const R_LARCH_DELETE: u32 = 101; -/// Delete some bytes to ensure the instruction at PC + A aligned to -/// `A.next_power_of_two()`-byte boundary -pub const R_LARCH_ALIGN: u32 = 102; -/// 22-bit PC-relative offset with two trailing zeros -pub const R_LARCH_PCREL20_S2: u32 = 103; -/// Reserved -pub const R_LARCH_CFA: u32 = 104; -/// 6-bit in-place addition -pub const R_LARCH_ADD6: u32 = 105; -/// 6-bit in-place subtraction -pub const R_LARCH_SUB6: u32 = 106; -/// LEB128 in-place addition -pub const R_LARCH_ADD_ULEB128: u32 = 107; -/// LEB128 in-place subtraction -pub const R_LARCH_SUB_ULEB128: u32 = 108; -/// 64-bit PC relative -pub const R_LARCH_64_PCREL: u32 = 109; -/// 18..=37 bits of `S + A - PC` into the `pcaddu18i` instruction at `PC`, -/// and 2..=17 bits of `S + A - PC` into the `jirl` instruction at `PC + 4` -pub const R_LARCH_CALL36: u32 = 110; - -// Xtensa values Rel*::r_type`. -pub const R_XTENSA_NONE: u32 = 0; -pub const R_XTENSA_32: u32 = 1; -pub const R_XTENSA_RTLD: u32 = 2; -pub const R_XTENSA_GLOB_DAT: u32 = 3; -pub const R_XTENSA_JMP_SLOT: u32 = 4; -pub const R_XTENSA_RELATIVE: u32 = 5; -pub const R_XTENSA_PLT: u32 = 6; -pub const R_XTENSA_OP0: u32 = 8; -pub const R_XTENSA_OP1: u32 = 9; -pub const R_XTENSA_OP2: u32 = 10; -pub const R_XTENSA_ASM_EXPAND: u32 = 11; -pub const R_XTENSA_ASM_SIMPLIFY: u32 = 12; -pub const R_XTENSA_32_PCREL: u32 = 14; -pub const R_XTENSA_GNU_VTINHERIT: u32 = 15; -pub const R_XTENSA_GNU_VTENTRY: u32 = 16; -pub const R_XTENSA_DIFF8: u32 = 17; -pub const R_XTENSA_DIFF16: u32 = 18; -pub const R_XTENSA_DIFF32: u32 = 19; -pub const R_XTENSA_SLOT0_OP: u32 = 20; -pub const R_XTENSA_SLOT1_OP: u32 = 21; -pub const R_XTENSA_SLOT2_OP: u32 = 22; -pub const R_XTENSA_SLOT3_OP: u32 = 23; -pub const R_XTENSA_SLOT4_OP: u32 = 24; -pub const R_XTENSA_SLOT5_OP: u32 = 25; -pub const R_XTENSA_SLOT6_OP: u32 = 26; -pub const R_XTENSA_SLOT7_OP: u32 = 27; -pub const R_XTENSA_SLOT8_OP: u32 = 28; -pub const R_XTENSA_SLOT9_OP: u32 = 29; -pub const R_XTENSA_SLOT10_OP: u32 = 30; -pub const R_XTENSA_SLOT11_OP: u32 = 31; -pub const R_XTENSA_SLOT12_OP: u32 = 32; -pub const R_XTENSA_SLOT13_OP: u32 = 33; -pub const R_XTENSA_SLOT14_OP: u32 = 34; -pub const R_XTENSA_SLOT0_ALT: u32 = 35; -pub const R_XTENSA_SLOT1_ALT: u32 = 36; -pub const R_XTENSA_SLOT2_ALT: u32 = 37; -pub const R_XTENSA_SLOT3_ALT: u32 = 38; -pub const R_XTENSA_SLOT4_ALT: u32 = 39; -pub const R_XTENSA_SLOT5_ALT: u32 = 40; -pub const R_XTENSA_SLOT6_ALT: u32 = 41; -pub const R_XTENSA_SLOT7_ALT: u32 = 42; -pub const R_XTENSA_SLOT8_ALT: u32 = 43; -pub const R_XTENSA_SLOT9_ALT: u32 = 44; -pub const R_XTENSA_SLOT10_ALT: u32 = 45; -pub const R_XTENSA_SLOT11_ALT: u32 = 46; -pub const R_XTENSA_SLOT12_ALT: u32 = 47; -pub const R_XTENSA_SLOT13_ALT: u32 = 48; -pub const R_XTENSA_SLOT14_ALT: u32 = 49; -pub const R_XTENSA_TLSDESC_FN: u32 = 50; -pub const R_XTENSA_TLSDESC_ARG: u32 = 51; -pub const R_XTENSA_TLS_DTPOFF: u32 = 52; -pub const R_XTENSA_TLS_TPOFF: u32 = 53; -pub const R_XTENSA_TLS_FUNC: u32 = 54; -pub const R_XTENSA_TLS_ARG: u32 = 55; -pub const R_XTENSA_TLS_CALL: u32 = 56; -pub const R_XTENSA_PDIFF8: u32 = 57; -pub const R_XTENSA_PDIFF16: u32 = 58; -pub const R_XTENSA_PDIFF32: u32 = 59; -pub const R_XTENSA_NDIFF8: u32 = 60; -pub const R_XTENSA_NDIFF16: u32 = 61; -pub const R_XTENSA_NDIFF32: u32 = 62; - -#[allow(non_upper_case_globals)] -pub const Tag_File: u8 = 1; -#[allow(non_upper_case_globals)] -pub const Tag_Section: u8 = 2; -#[allow(non_upper_case_globals)] -pub const Tag_Symbol: u8 = 3; - -unsafe_impl_endian_pod!( - FileHeader32, - FileHeader64, - SectionHeader32, - SectionHeader64, - CompressionHeader32, - CompressionHeader64, - Sym32, - Sym64, - Syminfo32, - Syminfo64, - Rel32, - Rel64, - Rela32, - Rela64, - ProgramHeader32, - ProgramHeader64, - Dyn32, - Dyn64, - Versym, - Verdef, - Verdaux, - Verneed, - Vernaux, - NoteHeader32, - NoteHeader64, - HashHeader, - GnuHashHeader, -); diff --git a/vendor/object/src/endian.rs b/vendor/object/src/endian.rs deleted file mode 100644 index e4a36ba..0000000 --- a/vendor/object/src/endian.rs +++ /dev/null @@ -1,831 +0,0 @@ -//! Types for compile-time and run-time endianness. - -use crate::pod::Pod; -use core::fmt::{self, Debug}; -use core::marker::PhantomData; - -/// A trait for using an endianness specification. -/// -/// Provides methods for converting between the specified endianness and -/// the native endianness of the target machine. -/// -/// This trait does not require that the endianness is known at compile time. -pub trait Endian: Debug + Default + Clone + Copy + PartialEq + Eq + 'static { - /// Construct a specification for the endianness of some values. - /// - /// Returns `None` if the type does not support specifying the given endianness. - fn from_big_endian(big_endian: bool) -> Option; - - /// Construct a specification for the endianness of some values. - /// - /// Returns `None` if the type does not support specifying the given endianness. - fn from_little_endian(little_endian: bool) -> Option { - Self::from_big_endian(!little_endian) - } - - /// 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() - } - - /// Converts an unsigned 16 bit integer to native endian. - #[inline] - fn read_u16(self, n: u16) -> u16 { - if self.is_big_endian() { - u16::from_be(n) - } else { - u16::from_le(n) - } - } - - /// Converts an unsigned 32 bit integer to native endian. - #[inline] - fn read_u32(self, n: u32) -> u32 { - if self.is_big_endian() { - u32::from_be(n) - } else { - u32::from_le(n) - } - } - - /// Converts an unsigned 64 bit integer to native endian. - #[inline] - fn read_u64(self, n: u64) -> u64 { - if self.is_big_endian() { - u64::from_be(n) - } else { - u64::from_le(n) - } - } - - /// Converts a signed 16 bit integer to native endian. - #[inline] - fn read_i16(self, n: i16) -> i16 { - if self.is_big_endian() { - i16::from_be(n) - } else { - i16::from_le(n) - } - } - - /// Converts a signed 32 bit integer to native endian. - #[inline] - fn read_i32(self, n: i32) -> i32 { - if self.is_big_endian() { - i32::from_be(n) - } else { - i32::from_le(n) - } - } - - /// Converts a signed 64 bit integer to native endian. - #[inline] - fn read_i64(self, n: i64) -> i64 { - if self.is_big_endian() { - i64::from_be(n) - } else { - i64::from_le(n) - } - } - - /// Converts an unaligned unsigned 16 bit integer to native endian. - #[inline] - fn read_u16_bytes(self, n: [u8; 2]) -> u16 { - if self.is_big_endian() { - u16::from_be_bytes(n) - } else { - u16::from_le_bytes(n) - } - } - - /// Converts an unaligned unsigned 32 bit integer to native endian. - #[inline] - fn read_u32_bytes(self, n: [u8; 4]) -> u32 { - if self.is_big_endian() { - u32::from_be_bytes(n) - } else { - u32::from_le_bytes(n) - } - } - - /// Converts an unaligned unsigned 64 bit integer to native endian. - #[inline] - fn read_u64_bytes(self, n: [u8; 8]) -> u64 { - if self.is_big_endian() { - u64::from_be_bytes(n) - } else { - u64::from_le_bytes(n) - } - } - - /// Converts an unaligned signed 16 bit integer to native endian. - #[inline] - fn read_i16_bytes(self, n: [u8; 2]) -> i16 { - if self.is_big_endian() { - i16::from_be_bytes(n) - } else { - i16::from_le_bytes(n) - } - } - - /// Converts an unaligned signed 32 bit integer to native endian. - #[inline] - fn read_i32_bytes(self, n: [u8; 4]) -> i32 { - if self.is_big_endian() { - i32::from_be_bytes(n) - } else { - i32::from_le_bytes(n) - } - } - - /// Converts an unaligned signed 64 bit integer to native endian. - #[inline] - fn read_i64_bytes(self, n: [u8; 8]) -> i64 { - if self.is_big_endian() { - i64::from_be_bytes(n) - } else { - i64::from_le_bytes(n) - } - } - - /// Converts an unsigned 16 bit integer from native endian. - #[inline] - fn write_u16(self, n: u16) -> u16 { - if self.is_big_endian() { - u16::to_be(n) - } else { - u16::to_le(n) - } - } - - /// Converts an unsigned 32 bit integer from native endian. - #[inline] - fn write_u32(self, n: u32) -> u32 { - if self.is_big_endian() { - u32::to_be(n) - } else { - u32::to_le(n) - } - } - - /// Converts an unsigned 64 bit integer from native endian. - #[inline] - fn write_u64(self, n: u64) -> u64 { - if self.is_big_endian() { - u64::to_be(n) - } else { - u64::to_le(n) - } - } - - /// Converts a signed 16 bit integer from native endian. - #[inline] - fn write_i16(self, n: i16) -> i16 { - if self.is_big_endian() { - i16::to_be(n) - } else { - i16::to_le(n) - } - } - - /// Converts a signed 32 bit integer from native endian. - #[inline] - fn write_i32(self, n: i32) -> i32 { - if self.is_big_endian() { - i32::to_be(n) - } else { - i32::to_le(n) - } - } - - /// Converts a signed 64 bit integer from native endian. - #[inline] - fn write_i64(self, n: i64) -> i64 { - if self.is_big_endian() { - i64::to_be(n) - } else { - i64::to_le(n) - } - } - - /// Converts an unaligned unsigned 16 bit integer from native endian. - #[inline] - fn write_u16_bytes(self, n: u16) -> [u8; 2] { - if self.is_big_endian() { - u16::to_be_bytes(n) - } else { - u16::to_le_bytes(n) - } - } - - /// Converts an unaligned unsigned 32 bit integer from native endian. - #[inline] - fn write_u32_bytes(self, n: u32) -> [u8; 4] { - if self.is_big_endian() { - u32::to_be_bytes(n) - } else { - u32::to_le_bytes(n) - } - } - - /// Converts an unaligned unsigned 64 bit integer from native endian. - #[inline] - fn write_u64_bytes(self, n: u64) -> [u8; 8] { - if self.is_big_endian() { - u64::to_be_bytes(n) - } else { - u64::to_le_bytes(n) - } - } - - /// Converts an unaligned signed 16 bit integer from native endian. - #[inline] - fn write_i16_bytes(self, n: i16) -> [u8; 2] { - if self.is_big_endian() { - i16::to_be_bytes(n) - } else { - i16::to_le_bytes(n) - } - } - - /// Converts an unaligned signed 32 bit integer from native endian. - #[inline] - fn write_i32_bytes(self, n: i32) -> [u8; 4] { - if self.is_big_endian() { - i32::to_be_bytes(n) - } else { - i32::to_le_bytes(n) - } - } - - /// Converts an unaligned signed 64 bit integer from native endian. - #[inline] - fn write_i64_bytes(self, n: i64) -> [u8; 8] { - if self.is_big_endian() { - i64::to_be_bytes(n) - } else { - i64::to_le_bytes(n) - } - } -} - -/// An endianness that is selectable at run-time. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum Endianness { - /// Little endian byte order. - Little, - /// Big endian byte order. - Big, -} - -impl Default for Endianness { - #[cfg(target_endian = "little")] - #[inline] - fn default() -> Endianness { - Endianness::Little - } - - #[cfg(target_endian = "big")] - #[inline] - fn default() -> Endianness { - Endianness::Big - } -} - -impl Endian for Endianness { - #[inline] - fn from_big_endian(big_endian: bool) -> Option { - Some(if big_endian { - Endianness::Big - } else { - Endianness::Little - }) - } - - #[inline] - fn is_big_endian(self) -> bool { - self != Endianness::Little - } -} - -/// Compile-time little endian byte order. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LittleEndian; - -impl Default for LittleEndian { - #[inline] - fn default() -> LittleEndian { - LittleEndian - } -} - -impl Endian for LittleEndian { - #[inline] - fn from_big_endian(big_endian: bool) -> Option { - if big_endian { - None - } else { - Some(LittleEndian) - } - } - - #[inline] - fn is_big_endian(self) -> bool { - false - } -} - -/// Compile-time big endian byte order. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct BigEndian; - -impl Default for BigEndian { - #[inline] - fn default() -> BigEndian { - BigEndian - } -} - -impl Endian for BigEndian { - #[inline] - fn from_big_endian(big_endian: bool) -> Option { - if big_endian { - Some(BigEndian) - } else { - None - } - } - - #[inline] - fn is_big_endian(self) -> bool { - true - } -} - -/// The native endianness 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 endianness 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; - -macro_rules! unsafe_impl_endian_pod { - ($($struct_name:ident),+ $(,)?) => { - $( - unsafe impl Pod for $struct_name { } - )+ - } -} - -#[cfg(not(feature = "unaligned"))] -mod aligned { - use super::{fmt, Endian, PhantomData, Pod}; - - /// A `u16` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct U16(u16, PhantomData); - - impl U16 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 2]) -> Self { - Self(u16::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u16) -> Self { - Self(e.write_u16(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u16 { - e.read_u16(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u16) { - self.0 = e.write_u16(n); - } - } - - /// A `u32` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct U32(u32, PhantomData); - - impl U32 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 4]) -> Self { - Self(u32::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u32) -> Self { - Self(e.write_u32(n), PhantomData) - } - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u32 { - e.read_u32(self.0) - } - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u32) { - self.0 = e.write_u32(n); - } - } - - /// A `u64` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct U64(u64, PhantomData); - - impl U64 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 8]) -> Self { - Self(u64::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u64) -> Self { - Self(e.write_u64(n), PhantomData) - } - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u64 { - e.read_u64(self.0) - } - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u64) { - self.0 = e.write_u64(n); - } - } - - /// An `i16` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct I16(i16, PhantomData); - - impl I16 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 2]) -> Self { - Self(i16::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i16) -> Self { - Self(e.write_i16(n), PhantomData) - } - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i16 { - e.read_i16(self.0) - } - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i16) { - self.0 = e.write_i16(n); - } - } - - /// An `i32` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct I32(i32, PhantomData); - - impl I32 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 4]) -> Self { - Self(i32::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i32) -> Self { - Self(e.write_i32(n), PhantomData) - } - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i32 { - e.read_i32(self.0) - } - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i32) { - self.0 = e.write_i32(n); - } - } - - /// An `i64` value with an externally specified endianness of type `E`. - #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[repr(transparent)] - pub struct I64(i64, PhantomData); - - impl I64 { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 8]) -> Self { - Self(i64::from_ne_bytes(n), PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i64) -> Self { - Self(e.write_i64(n), PhantomData) - } - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i64 { - e.read_i64(self.0) - } - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i64) { - self.0 = e.write_i64(n); - } - } - - impl fmt::Debug for U16 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "U16({:x})", self.0) - } - } - - impl fmt::Debug for U32 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "U32({:x})", self.0) - } - } - - impl fmt::Debug for U64 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "U64({:x})", self.0) - } - } - - impl fmt::Debug for I16 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "I16({:x})", self.0) - } - } - - impl fmt::Debug for I32 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "I32({:x})", self.0) - } - } - - impl fmt::Debug for I64 { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "I64({:x})", self.0) - } - } - - unsafe_impl_endian_pod!(U16, U32, U64, I16, I32, I64); -} - -#[cfg(not(feature = "unaligned"))] -pub use aligned::*; - -/// A `u16` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type U16 = U16Bytes; - -/// A `u32` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type U32 = U32Bytes; - -/// A `u64` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type U64 = U64Bytes; - -/// An `i16` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type I16 = I16Bytes; - -/// An `i32` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type I32 = I32Bytes; - -/// An `i64` value with an externally specified endianness of type `E`. -#[cfg(feature = "unaligned")] -pub type I64 = I64Bytes; - -/// An unaligned `u16` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct U16Bytes([u8; 2], PhantomData); - -impl U16Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 2]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u16) -> Self { - Self(e.write_u16_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u16 { - e.read_u16_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u16) { - self.0 = e.write_u16_bytes(n); - } -} - -/// An unaligned `u32` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct U32Bytes([u8; 4], PhantomData); - -impl U32Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 4]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u32) -> Self { - Self(e.write_u32_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u32 { - e.read_u32_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u32) { - self.0 = e.write_u32_bytes(n); - } -} - -/// An unaligned `u64` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct U64Bytes([u8; 8], PhantomData); - -impl U64Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 8]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: u64) -> Self { - Self(e.write_u64_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> u64 { - e.read_u64_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: u64) { - self.0 = e.write_u64_bytes(n); - } -} - -/// An unaligned `i16` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct I16Bytes([u8; 2], PhantomData); - -impl I16Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 2]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i16) -> Self { - Self(e.write_i16_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i16 { - e.read_i16_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i16) { - self.0 = e.write_i16_bytes(n); - } -} - -/// An unaligned `i32` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct I32Bytes([u8; 4], PhantomData); - -impl I32Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 4]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i32) -> Self { - Self(e.write_i32_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i32 { - e.read_i32_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i32) { - self.0 = e.write_i32_bytes(n); - } -} - -/// An unaligned `i64` value with an externally specified endianness of type `E`. -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct I64Bytes([u8; 8], PhantomData); - -impl I64Bytes { - /// Construct a new value given bytes that already have the required endianness. - pub fn from_bytes(n: [u8; 8]) -> Self { - Self(n, PhantomData) - } - - /// Construct a new value given a native endian value. - pub fn new(e: E, n: i64) -> Self { - Self(e.write_i64_bytes(n), PhantomData) - } - - /// Return the value as a native endian value. - pub fn get(self, e: E) -> i64 { - e.read_i64_bytes(self.0) - } - - /// Set the value given a native endian value. - pub fn set(&mut self, e: E, n: i64) { - self.0 = e.write_i64_bytes(n); - } -} - -impl fmt::Debug for U16Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "U16({:x}, {:x})", self.0[0], self.0[1],) - } -} - -impl fmt::Debug for U32Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "U32({:x}, {:x}, {:x}, {:x})", - self.0[0], self.0[1], self.0[2], self.0[3], - ) - } -} - -impl fmt::Debug for U64Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "U64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})", - self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7], - ) - } -} - -impl fmt::Debug for I16Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "I16({:x}, {:x})", self.0[0], self.0[1],) - } -} - -impl fmt::Debug for I32Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "I32({:x}, {:x}, {:x}, {:x})", - self.0[0], self.0[1], self.0[2], self.0[3], - ) - } -} - -impl fmt::Debug for I64Bytes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "I64({:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x}, {:x})", - self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7], - ) - } -} - -unsafe_impl_endian_pod!(U16Bytes, U32Bytes, U64Bytes, I16Bytes, I32Bytes, I64Bytes); diff --git a/vendor/object/src/lib.rs b/vendor/object/src/lib.rs deleted file mode 100644 index 5956e06..0000000 --- a/vendor/object/src/lib.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! # `object` -//! -//! The `object` crate provides a unified interface to working with object files -//! across platforms. It supports reading relocatable object files and executable files, -//! and writing relocatable object files and some executable files. -//! -//! ## Raw struct definitions -//! -//! Raw structs are defined for: [ELF](elf), [Mach-O](macho), [PE/COFF](pe), -//! [XCOFF](xcoff), [archive]. -//! Types and traits for zerocopy support are defined in the [`pod`] and [`endian`] modules. -//! -//! ## Unified read API -//! -//! The [`read`] module provides a unified read API using the [`read::Object`] trait. -//! There is an implementation of this trait for [`read::File`], which allows reading any -//! file format, as well as implementations for each file format. -//! -//! ## Low level read API -//! -//! The [`read#modules`] submodules define helpers that operate on the raw structs. -//! These can be used instead of the unified API, or in conjunction with it to access -//! details that are not available via the unified API. -//! -//! ## Unified write API -//! -//! The [`mod@write`] module provides a unified write API for relocatable object files -//! using [`write::Object`]. This does not support writing executable files. -//! -//! ## Low level write API -//! -//! The [`mod@write#modules`] submodules define helpers for writing the raw structs. -//! -//! ## Shared definitions -//! -//! The crate provides a number of definitions that are used by both the read and write -//! APIs. These are defined at the top level module, but none of these are the main entry -//! points of the crate. - -#![deny(missing_docs)] -#![deny(missing_debug_implementations)] -#![no_std] -#![warn(rust_2018_idioms)] -// Style. -#![allow(clippy::collapsible_if)] -#![allow(clippy::comparison_chain)] -#![allow(clippy::manual_flatten)] -#![allow(clippy::match_like_matches_macro)] -#![allow(clippy::single_match)] -#![allow(clippy::type_complexity)] -// Occurs due to fallible iteration. -#![allow(clippy::should_implement_trait)] -// Unit errors are converted to other types by callers. -#![allow(clippy::result_unit_err)] -// Worse readability sometimes. -#![allow(clippy::collapsible_else_if)] - -#[cfg(feature = "cargo-all")] -compile_error!("'--all-features' is not supported; use '--features all' instead"); - -#[cfg(any(feature = "read_core", feature = "write_core"))] -#[allow(unused_imports)] -#[macro_use] -extern crate alloc; - -#[cfg(feature = "std")] -#[allow(unused_imports)] -#[macro_use] -extern crate std; - -mod common; -pub use common::*; - -#[macro_use] -pub mod endian; -pub use endian::*; - -#[macro_use] -pub mod pod; -pub use pod::*; - -#[cfg(feature = "read_core")] -pub mod read; -#[cfg(feature = "read_core")] -pub use read::*; - -#[cfg(feature = "write_core")] -pub mod write; - -#[cfg(feature = "archive")] -pub mod archive; -#[cfg(feature = "elf")] -pub mod elf; -#[cfg(feature = "macho")] -pub mod macho; -#[cfg(any(feature = "coff", feature = "pe"))] -pub mod pe; -#[cfg(feature = "xcoff")] -pub mod xcoff; diff --git a/vendor/object/src/macho.rs b/vendor/object/src/macho.rs deleted file mode 100644 index 3cd38e0..0000000 --- a/vendor/object/src/macho.rs +++ /dev/null @@ -1,3307 +0,0 @@ -//! Mach-O definitions. -//! -//! These definitions are independent of read/write support, although we do implement -//! some traits useful for those. -//! -//! This module is based heavily on header files from MacOSX11.1.sdk. - -#![allow(missing_docs)] - -use crate::endian::{BigEndian, Endian, U64Bytes, U16, U32, U64}; -use crate::pod::Pod; - -// Definitions from "/usr/include/mach/machine.h". - -/* - * Capability bits used in the definition of cpu_type. - */ - -/// mask for architecture bits -pub const CPU_ARCH_MASK: u32 = 0xff00_0000; -/// 64 bit ABI -pub const CPU_ARCH_ABI64: u32 = 0x0100_0000; -/// ABI for 64-bit hardware with 32-bit types; LP32 -pub const CPU_ARCH_ABI64_32: u32 = 0x0200_0000; - -/* - * Machine types known by all. - */ - -pub const CPU_TYPE_ANY: u32 = !0; - -pub const CPU_TYPE_VAX: u32 = 1; -pub const CPU_TYPE_MC680X0: u32 = 6; -pub const CPU_TYPE_X86: u32 = 7; -pub const CPU_TYPE_X86_64: u32 = CPU_TYPE_X86 | CPU_ARCH_ABI64; -pub const CPU_TYPE_MIPS: u32 = 8; -pub const CPU_TYPE_MC98000: u32 = 10; -pub const CPU_TYPE_HPPA: u32 = 11; -pub const CPU_TYPE_ARM: u32 = 12; -pub const CPU_TYPE_ARM64: u32 = CPU_TYPE_ARM | CPU_ARCH_ABI64; -pub const CPU_TYPE_ARM64_32: u32 = CPU_TYPE_ARM | CPU_ARCH_ABI64_32; -pub const CPU_TYPE_MC88000: u32 = 13; -pub const CPU_TYPE_SPARC: u32 = 14; -pub const CPU_TYPE_I860: u32 = 15; -pub const CPU_TYPE_ALPHA: u32 = 16; -pub const CPU_TYPE_POWERPC: u32 = 18; -pub const CPU_TYPE_POWERPC64: u32 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64; - -/* - * Capability bits used in the definition of cpu_subtype. - */ -/// mask for feature flags -pub const CPU_SUBTYPE_MASK: u32 = 0xff00_0000; -/// 64 bit libraries -pub const CPU_SUBTYPE_LIB64: u32 = 0x8000_0000; -/// pointer authentication with versioned ABI -pub const CPU_SUBTYPE_PTRAUTH_ABI: u32 = 0x8000_0000; - -/// When selecting a slice, ANY will pick the slice with the best -/// grading for the selected cpu_type_t, unlike the "ALL" subtypes, -/// which are the slices that can run on any hardware for that cpu type. -pub const CPU_SUBTYPE_ANY: u32 = !0; - -/* - * Object files that are hand-crafted to run on any - * implementation of an architecture are tagged with - * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as - * the "ALL" subtype of an architecture except that it allows us - * to easily find object files that may need to be modified - * whenever a new implementation of an architecture comes out. - * - * It is the responsibility of the implementor to make sure the - * software handles unsupported implementations elegantly. - */ -pub const CPU_SUBTYPE_MULTIPLE: u32 = !0; -pub const CPU_SUBTYPE_LITTLE_ENDIAN: u32 = 0; -pub const CPU_SUBTYPE_BIG_ENDIAN: u32 = 1; - -/* - * VAX subtypes (these do *not* necessary conform to the actual cpu - * ID assigned by DEC available via the SID register). - */ - -pub const CPU_SUBTYPE_VAX_ALL: u32 = 0; -pub const CPU_SUBTYPE_VAX780: u32 = 1; -pub const CPU_SUBTYPE_VAX785: u32 = 2; -pub const CPU_SUBTYPE_VAX750: u32 = 3; -pub const CPU_SUBTYPE_VAX730: u32 = 4; -pub const CPU_SUBTYPE_UVAXI: u32 = 5; -pub const CPU_SUBTYPE_UVAXII: u32 = 6; -pub const CPU_SUBTYPE_VAX8200: u32 = 7; -pub const CPU_SUBTYPE_VAX8500: u32 = 8; -pub const CPU_SUBTYPE_VAX8600: u32 = 9; -pub const CPU_SUBTYPE_VAX8650: u32 = 10; -pub const CPU_SUBTYPE_VAX8800: u32 = 11; -pub const CPU_SUBTYPE_UVAXIII: u32 = 12; - -/* - * 680x0 subtypes - * - * The subtype definitions here are unusual for historical reasons. - * NeXT used to consider 68030 code as generic 68000 code. For - * backwards compatibility: - * - * CPU_SUBTYPE_MC68030 symbol has been preserved for source code - * compatibility. - * - * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same - * subtype as CPU_SUBTYPE_MC68030 for binary comatability. - * - * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object - * files to be tagged as containing 68030-specific instructions. - */ - -pub const CPU_SUBTYPE_MC680X0_ALL: u32 = 1; -// compat -pub const CPU_SUBTYPE_MC68030: u32 = 1; -pub const CPU_SUBTYPE_MC68040: u32 = 2; -pub const CPU_SUBTYPE_MC68030_ONLY: u32 = 3; - -/* - * I386 subtypes - */ - -#[inline] -pub const fn cpu_subtype_intel(f: u32, m: u32) -> u32 { - f + (m << 4) -} - -pub const CPU_SUBTYPE_I386_ALL: u32 = cpu_subtype_intel(3, 0); -pub const CPU_SUBTYPE_386: u32 = cpu_subtype_intel(3, 0); -pub const CPU_SUBTYPE_486: u32 = cpu_subtype_intel(4, 0); -pub const CPU_SUBTYPE_486SX: u32 = cpu_subtype_intel(4, 8); -pub const CPU_SUBTYPE_586: u32 = cpu_subtype_intel(5, 0); -pub const CPU_SUBTYPE_PENT: u32 = cpu_subtype_intel(5, 0); -pub const CPU_SUBTYPE_PENTPRO: u32 = cpu_subtype_intel(6, 1); -pub const CPU_SUBTYPE_PENTII_M3: u32 = cpu_subtype_intel(6, 3); -pub const CPU_SUBTYPE_PENTII_M5: u32 = cpu_subtype_intel(6, 5); -pub const CPU_SUBTYPE_CELERON: u32 = cpu_subtype_intel(7, 6); -pub const CPU_SUBTYPE_CELERON_MOBILE: u32 = cpu_subtype_intel(7, 7); -pub const CPU_SUBTYPE_PENTIUM_3: u32 = cpu_subtype_intel(8, 0); -pub const CPU_SUBTYPE_PENTIUM_3_M: u32 = cpu_subtype_intel(8, 1); -pub const CPU_SUBTYPE_PENTIUM_3_XEON: u32 = cpu_subtype_intel(8, 2); -pub const CPU_SUBTYPE_PENTIUM_M: u32 = cpu_subtype_intel(9, 0); -pub const CPU_SUBTYPE_PENTIUM_4: u32 = cpu_subtype_intel(10, 0); -pub const CPU_SUBTYPE_PENTIUM_4_M: u32 = cpu_subtype_intel(10, 1); -pub const CPU_SUBTYPE_ITANIUM: u32 = cpu_subtype_intel(11, 0); -pub const CPU_SUBTYPE_ITANIUM_2: u32 = cpu_subtype_intel(11, 1); -pub const CPU_SUBTYPE_XEON: u32 = cpu_subtype_intel(12, 0); -pub const CPU_SUBTYPE_XEON_MP: u32 = cpu_subtype_intel(12, 1); - -#[inline] -pub const fn cpu_subtype_intel_family(x: u32) -> u32 { - x & 15 -} -pub const CPU_SUBTYPE_INTEL_FAMILY_MAX: u32 = 15; - -#[inline] -pub const fn cpu_subtype_intel_model(x: u32) -> u32 { - x >> 4 -} -pub const CPU_SUBTYPE_INTEL_MODEL_ALL: u32 = 0; - -/* - * X86 subtypes. - */ - -pub const CPU_SUBTYPE_X86_ALL: u32 = 3; -pub const CPU_SUBTYPE_X86_64_ALL: u32 = 3; -pub const CPU_SUBTYPE_X86_ARCH1: u32 = 4; -/// Haswell feature subset -pub const CPU_SUBTYPE_X86_64_H: u32 = 8; - -/* - * Mips subtypes. - */ - -pub const CPU_SUBTYPE_MIPS_ALL: u32 = 0; -pub const CPU_SUBTYPE_MIPS_R2300: u32 = 1; -pub const CPU_SUBTYPE_MIPS_R2600: u32 = 2; -pub const CPU_SUBTYPE_MIPS_R2800: u32 = 3; -/// pmax -pub const CPU_SUBTYPE_MIPS_R2000A: u32 = 4; -pub const CPU_SUBTYPE_MIPS_R2000: u32 = 5; -/// 3max -pub const CPU_SUBTYPE_MIPS_R3000A: u32 = 6; -pub const CPU_SUBTYPE_MIPS_R3000: u32 = 7; - -/* - * MC98000 (PowerPC) subtypes - */ -pub const CPU_SUBTYPE_MC98000_ALL: u32 = 0; -pub const CPU_SUBTYPE_MC98601: u32 = 1; - -/* - * HPPA subtypes for Hewlett-Packard HP-PA family of - * risc processors. Port by NeXT to 700 series. - */ - -pub const CPU_SUBTYPE_HPPA_ALL: u32 = 0; -pub const CPU_SUBTYPE_HPPA_7100LC: u32 = 1; - -/* - * MC88000 subtypes. - */ -pub const CPU_SUBTYPE_MC88000_ALL: u32 = 0; -pub const CPU_SUBTYPE_MC88100: u32 = 1; -pub const CPU_SUBTYPE_MC88110: u32 = 2; - -/* - * SPARC subtypes - */ -pub const CPU_SUBTYPE_SPARC_ALL: u32 = 0; - -/* - * I860 subtypes - */ -pub const CPU_SUBTYPE_I860_ALL: u32 = 0; -pub const CPU_SUBTYPE_I860_860: u32 = 1; - -/* - * PowerPC subtypes - */ -pub const CPU_SUBTYPE_POWERPC_ALL: u32 = 0; -pub const CPU_SUBTYPE_POWERPC_601: u32 = 1; -pub const CPU_SUBTYPE_POWERPC_602: u32 = 2; -pub const CPU_SUBTYPE_POWERPC_603: u32 = 3; -pub const CPU_SUBTYPE_POWERPC_603E: u32 = 4; -pub const CPU_SUBTYPE_POWERPC_603EV: u32 = 5; -pub const CPU_SUBTYPE_POWERPC_604: u32 = 6; -pub const CPU_SUBTYPE_POWERPC_604E: u32 = 7; -pub const CPU_SUBTYPE_POWERPC_620: u32 = 8; -pub const CPU_SUBTYPE_POWERPC_750: u32 = 9; -pub const CPU_SUBTYPE_POWERPC_7400: u32 = 10; -pub const CPU_SUBTYPE_POWERPC_7450: u32 = 11; -pub const CPU_SUBTYPE_POWERPC_970: u32 = 100; - -/* - * ARM subtypes - */ -pub const CPU_SUBTYPE_ARM_ALL: u32 = 0; -pub const CPU_SUBTYPE_ARM_V4T: u32 = 5; -pub const CPU_SUBTYPE_ARM_V6: u32 = 6; -pub const CPU_SUBTYPE_ARM_V5TEJ: u32 = 7; -pub const CPU_SUBTYPE_ARM_XSCALE: u32 = 8; -/// ARMv7-A and ARMv7-R -pub const CPU_SUBTYPE_ARM_V7: u32 = 9; -/// Cortex A9 -pub const CPU_SUBTYPE_ARM_V7F: u32 = 10; -/// Swift -pub const CPU_SUBTYPE_ARM_V7S: u32 = 11; -pub const CPU_SUBTYPE_ARM_V7K: u32 = 12; -pub const CPU_SUBTYPE_ARM_V8: u32 = 13; -/// Not meant to be run under xnu -pub const CPU_SUBTYPE_ARM_V6M: u32 = 14; -/// Not meant to be run under xnu -pub const CPU_SUBTYPE_ARM_V7M: u32 = 15; -/// Not meant to be run under xnu -pub const CPU_SUBTYPE_ARM_V7EM: u32 = 16; -/// Not meant to be run under xnu -pub const CPU_SUBTYPE_ARM_V8M: u32 = 17; - -/* - * ARM64 subtypes - */ -pub const CPU_SUBTYPE_ARM64_ALL: u32 = 0; -pub const CPU_SUBTYPE_ARM64_V8: u32 = 1; -pub const CPU_SUBTYPE_ARM64E: u32 = 2; - -/* - * ARM64_32 subtypes - */ -pub const CPU_SUBTYPE_ARM64_32_ALL: u32 = 0; -pub const CPU_SUBTYPE_ARM64_32_V8: u32 = 1; - -// Definitions from "/usr/include/mach/vm_prot.h". - -/// read permission -pub const VM_PROT_READ: u32 = 0x01; -/// write permission -pub const VM_PROT_WRITE: u32 = 0x02; -/// execute permission -pub const VM_PROT_EXECUTE: u32 = 0x04; - -// Definitions from https://opensource.apple.com/source/dyld/dyld-210.2.3/launch-cache/dyld_cache_format.h.auto.html - -/// The dyld cache header. -/// Corresponds to struct dyld_cache_header from dyld_cache_format.h. -/// This header has grown over time. Only the fields up to and including dyld_base_address -/// are guaranteed to be present. For all other fields, check the header size before -/// accessing the field. The header size is stored in mapping_offset; the mappings start -/// right after the theader. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DyldCacheHeader { - /// e.g. "dyld_v0 i386" - pub magic: [u8; 16], - /// file offset to first dyld_cache_mapping_info - pub mapping_offset: U32, // offset: 0x10 - /// number of dyld_cache_mapping_info entries - pub mapping_count: U32, // offset: 0x14 - /// file offset to first dyld_cache_image_info - pub images_offset: U32, // offset: 0x18 - /// number of dyld_cache_image_info entries - pub images_count: U32, // offset: 0x1c - /// base address of dyld when cache was built - pub dyld_base_address: U64, // offset: 0x20 - /// - reserved1: [u8; 32], // offset: 0x28 - /// file offset of where local symbols are stored - pub local_symbols_offset: U64, // offset: 0x48 - /// size of local symbols information - pub local_symbols_size: U64, // offset: 0x50 - /// unique value for each shared cache file - pub uuid: [u8; 16], // offset: 0x58 - /// - reserved2: [u8; 32], // offset: 0x68 - /// - reserved3: [u8; 32], // offset: 0x88 - /// - reserved4: [u8; 32], // offset: 0xa8 - /// - reserved5: [u8; 32], // offset: 0xc8 - /// - reserved6: [u8; 32], // offset: 0xe8 - /// - reserved7: [u8; 32], // offset: 0x108 - /// - reserved8: [u8; 32], // offset: 0x128 - /// - reserved9: [u8; 32], // offset: 0x148 - /// - reserved10: [u8; 32], // offset: 0x168 - /// file offset to first dyld_subcache_info - pub subcaches_offset: U32, // offset: 0x188 - /// number of dyld_subcache_info entries - pub subcaches_count: U32, // offset: 0x18c - /// the UUID of the .symbols subcache - pub symbols_subcache_uuid: [u8; 16], // offset: 0x190 - /// - reserved11: [u8; 32], // offset: 0x1a0 - /// file offset to first dyld_cache_image_info - /// Use this instead of images_offset if mapping_offset is at least 0x1c4. - pub images_across_all_subcaches_offset: U32, // offset: 0x1c0 - /// number of dyld_cache_image_info entries - /// Use this instead of images_count if mapping_offset is at least 0x1c4. - pub images_across_all_subcaches_count: U32, // offset: 0x1c4 -} - -/// Corresponds to struct dyld_cache_mapping_info from dyld_cache_format.h. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DyldCacheMappingInfo { - /// - pub address: U64, - /// - pub size: U64, - /// - pub file_offset: U64, - /// - pub max_prot: U32, - /// - pub init_prot: U32, -} - -/// Corresponds to struct dyld_cache_image_info from dyld_cache_format.h. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DyldCacheImageInfo { - /// - pub address: U64, - /// - pub mod_time: U64, - /// - pub inode: U64, - /// - pub path_file_offset: U32, - /// - pub pad: U32, -} - -/// Corresponds to a struct whose source code has not been published as of Nov 2021. -/// Added in the dyld cache version which shipped with macOS 12 / iOS 15. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DyldSubCacheInfo { - /// The UUID of this subcache. - pub uuid: [u8; 16], - /// The size of this subcache plus all previous subcaches. - pub cumulative_size: U64, -} - -// Definitions from "/usr/include/mach-o/loader.h". - -/* - * This header file describes the structures of the file format for "fat" - * architecture specific file (wrapper design). At the beginning of the file - * there is one `FatHeader` structure followed by a number of `FatArch*` - * structures. For each architecture in the file, specified by a pair of - * cputype and cpusubtype, the `FatHeader` describes the file offset, file - * size and alignment in the file of the architecture specific member. - * The padded bytes in the file to place each member on it's specific alignment - * are defined to be read as zeros and can be left as "holes" if the file system - * can support them as long as they read as zeros. - * - * All structures defined here are always written and read to/from disk - * in big-endian order. - */ - -pub const FAT_MAGIC: u32 = 0xcafe_babe; -/// NXSwapLong(FAT_MAGIC) -pub const FAT_CIGAM: u32 = 0xbeba_feca; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FatHeader { - /// FAT_MAGIC or FAT_MAGIC_64 - pub magic: U32, - /// number of structs that follow - pub nfat_arch: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FatArch32 { - /// cpu specifier (int) - pub cputype: U32, - /// machine specifier (int) - pub cpusubtype: U32, - /// file offset to this object file - pub offset: U32, - /// size of this object file - pub size: U32, - /// alignment as a power of 2 - pub align: U32, -} - -/* - * The support for the 64-bit fat file format described here is a work in - * progress and not yet fully supported in all the Apple Developer Tools. - * - * When a slice is greater than 4mb or an offset to a slice is greater than 4mb - * then the 64-bit fat file format is used. - */ -pub const FAT_MAGIC_64: u32 = 0xcafe_babf; -/// NXSwapLong(FAT_MAGIC_64) -pub const FAT_CIGAM_64: u32 = 0xbfba_feca; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FatArch64 { - /// cpu specifier (int) - pub cputype: U32, - /// machine specifier (int) - pub cpusubtype: U32, - /// file offset to this object file - pub offset: U64, - /// size of this object file - pub size: U64, - /// alignment as a power of 2 - pub align: U32, - /// reserved - pub reserved: U32, -} - -// Definitions from "/usr/include/mach-o/loader.h". - -/// The 32-bit mach header. -/// -/// Appears at the very beginning of the object file for 32-bit architectures. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct MachHeader32 { - /// mach magic number identifier - pub magic: U32, - /// cpu specifier - pub cputype: U32, - /// machine specifier - pub cpusubtype: U32, - /// type of file - pub filetype: U32, - /// number of load commands - pub ncmds: U32, - /// the size of all the load commands - pub sizeofcmds: U32, - /// flags - pub flags: U32, -} - -// Values for `MachHeader32::magic`. -/// the mach magic number -pub const MH_MAGIC: u32 = 0xfeed_face; -/// NXSwapInt(MH_MAGIC) -pub const MH_CIGAM: u32 = 0xcefa_edfe; - -/// The 64-bit mach header. -/// -/// Appears at the very beginning of object files for 64-bit architectures. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct MachHeader64 { - /// mach magic number identifier - pub magic: U32, - /// cpu specifier - pub cputype: U32, - /// machine specifier - pub cpusubtype: U32, - /// type of file - pub filetype: U32, - /// number of load commands - pub ncmds: U32, - /// the size of all the load commands - pub sizeofcmds: U32, - /// flags - pub flags: U32, - /// reserved - pub reserved: U32, -} - -// Values for `MachHeader64::magic`. -/// the 64-bit mach magic number -pub const MH_MAGIC_64: u32 = 0xfeed_facf; -/// NXSwapInt(MH_MAGIC_64) -pub const MH_CIGAM_64: u32 = 0xcffa_edfe; - -/* - * The layout of the file depends on the filetype. For all but the MH_OBJECT - * file type the segments are padded out and aligned on a segment alignment - * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB, - * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part - * of their first segment. - * - * The file type MH_OBJECT is a compact format intended as output of the - * assembler and input (and possibly output) of the link editor (the .o - * format). All sections are in one unnamed segment with no segment padding. - * This format is used as an executable format when the file is so small the - * segment padding greatly increases its size. - * - * The file type MH_PRELOAD is an executable format intended for things that - * are not executed under the kernel (proms, stand alones, kernels, etc). The - * format can be executed under the kernel but may demand paged it and not - * preload it before execution. - * - * A core file is in MH_CORE format and can be any in an arbritray legal - * Mach-O file. - */ - -// Values for `MachHeader*::filetype`. -/// relocatable object file -pub const MH_OBJECT: u32 = 0x1; -/// demand paged executable file -pub const MH_EXECUTE: u32 = 0x2; -/// fixed VM shared library file -pub const MH_FVMLIB: u32 = 0x3; -/// core file -pub const MH_CORE: u32 = 0x4; -/// preloaded executable file -pub const MH_PRELOAD: u32 = 0x5; -/// dynamically bound shared library -pub const MH_DYLIB: u32 = 0x6; -/// dynamic link editor -pub const MH_DYLINKER: u32 = 0x7; -/// dynamically bound bundle file -pub const MH_BUNDLE: u32 = 0x8; -/// shared library stub for static linking only, no section contents -pub const MH_DYLIB_STUB: u32 = 0x9; -/// companion file with only debug sections -pub const MH_DSYM: u32 = 0xa; -/// x86_64 kexts -pub const MH_KEXT_BUNDLE: u32 = 0xb; -/// set of mach-o's -pub const MH_FILESET: u32 = 0xc; - -// Values for `MachHeader*::flags`. -/// the object file has no undefined references -pub const MH_NOUNDEFS: u32 = 0x1; -/// the object file is the output of an incremental link against a base file and can't be link edited again -pub const MH_INCRLINK: u32 = 0x2; -/// the object file is input for the dynamic linker and can't be statically link edited again -pub const MH_DYLDLINK: u32 = 0x4; -/// the object file's undefined references are bound by the dynamic linker when loaded. -pub const MH_BINDATLOAD: u32 = 0x8; -/// the file has its dynamic undefined references prebound. -pub const MH_PREBOUND: u32 = 0x10; -/// the file has its read-only and read-write segments split -pub const MH_SPLIT_SEGS: u32 = 0x20; -/// the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) -pub const MH_LAZY_INIT: u32 = 0x40; -/// the image is using two-level name space bindings -pub const MH_TWOLEVEL: u32 = 0x80; -/// the executable is forcing all images to use flat name space bindings -pub const MH_FORCE_FLAT: u32 = 0x100; -/// this umbrella guarantees no multiple definitions of symbols in its sub-images so the two-level namespace hints can always be used. -pub const MH_NOMULTIDEFS: u32 = 0x200; -/// do not have dyld notify the prebinding agent about this executable -pub const MH_NOFIXPREBINDING: u32 = 0x400; -/// the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. -pub const MH_PREBINDABLE: u32 = 0x800; -/// indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. -pub const MH_ALLMODSBOUND: u32 = 0x1000; -/// safe to divide up the sections into sub-sections via symbols for dead code stripping -pub const MH_SUBSECTIONS_VIA_SYMBOLS: u32 = 0x2000; -/// the binary has been canonicalized via the unprebind operation -pub const MH_CANONICAL: u32 = 0x4000; -/// the final linked image contains external weak symbols -pub const MH_WEAK_DEFINES: u32 = 0x8000; -/// the final linked image uses weak symbols -pub const MH_BINDS_TO_WEAK: u32 = 0x10000; -/// When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes. -pub const MH_ALLOW_STACK_EXECUTION: u32 = 0x20000; -/// When this bit is set, the binary declares it is safe for use in processes with uid zero -pub const MH_ROOT_SAFE: u32 = 0x40000; -/// When this bit is set, the binary declares it is safe for use in processes when issetugid() is true -pub const MH_SETUID_SAFE: u32 = 0x80000; -/// When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported -pub const MH_NO_REEXPORTED_DYLIBS: u32 = 0x10_0000; -/// When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. -pub const MH_PIE: u32 = 0x20_0000; -/// Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib. -pub const MH_DEAD_STRIPPABLE_DYLIB: u32 = 0x40_0000; -/// Contains a section of type S_THREAD_LOCAL_VARIABLES -pub const MH_HAS_TLV_DESCRIPTORS: u32 = 0x80_0000; -/// When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes. -pub const MH_NO_HEAP_EXECUTION: u32 = 0x100_0000; -/// The code was linked for use in an application extension. -pub const MH_APP_EXTENSION_SAFE: u32 = 0x0200_0000; -/// The external symbols listed in the nlist symbol table do not include all the symbols listed in the dyld info. -pub const MH_NLIST_OUTOFSYNC_WITH_DYLDINFO: u32 = 0x0400_0000; -/// Allow LC_MIN_VERSION_MACOS and LC_BUILD_VERSION load commands with -/// the platforms macOS, iOSMac, iOSSimulator, tvOSSimulator and watchOSSimulator. -pub const MH_SIM_SUPPORT: u32 = 0x0800_0000; -/// Only for use on dylibs. When this bit is set, the dylib is part of the dyld -/// shared cache, rather than loose in the filesystem. -pub const MH_DYLIB_IN_CACHE: u32 = 0x8000_0000; - -/// Common fields at the start of every load command. -/// -/// The load commands directly follow the mach_header. The total size of all -/// of the commands is given by the sizeofcmds field in the mach_header. All -/// load commands must have as their first two fields `cmd` and `cmdsize`. The `cmd` -/// field is filled in with a constant for that command type. Each command type -/// has a structure specifically for it. The `cmdsize` field is the size in bytes -/// of the particular load command structure plus anything that follows it that -/// is a part of the load command (i.e. section structures, strings, etc.). To -/// advance to the next load command the `cmdsize` can be added to the offset or -/// pointer of the current load command. The `cmdsize` for 32-bit architectures -/// MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple -/// of 8 bytes (these are forever the maximum alignment of any load commands). -/// The padded bytes must be zero. All tables in the object file must also -/// follow these rules so the file can be memory mapped. Otherwise the pointers -/// to these tables will not work well or at all on some machines. With all -/// padding zeroed like objects will compare byte for byte. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct LoadCommand { - /// Type of load command. - /// - /// One of the `LC_*` constants. - pub cmd: U32, - /// Total size of command in bytes. - pub cmdsize: U32, -} - -/* - * After MacOS X 10.1 when a new load command is added that is required to be - * understood by the dynamic linker for the image to execute properly the - * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic - * linker sees such a load command it it does not understand will issue a - * "unknown load command required for execution" error and refuse to use the - * image. Other load commands without this bit that are not understood will - * simply be ignored. - */ -pub const LC_REQ_DYLD: u32 = 0x8000_0000; - -/* Constants for the cmd field of all load commands, the type */ -/// segment of this file to be mapped -pub const LC_SEGMENT: u32 = 0x1; -/// link-edit stab symbol table info -pub const LC_SYMTAB: u32 = 0x2; -/// link-edit gdb symbol table info (obsolete) -pub const LC_SYMSEG: u32 = 0x3; -/// thread -pub const LC_THREAD: u32 = 0x4; -/// unix thread (includes a stack) -pub const LC_UNIXTHREAD: u32 = 0x5; -/// load a specified fixed VM shared library -pub const LC_LOADFVMLIB: u32 = 0x6; -/// fixed VM shared library identification -pub const LC_IDFVMLIB: u32 = 0x7; -/// object identification info (obsolete) -pub const LC_IDENT: u32 = 0x8; -/// fixed VM file inclusion (internal use) -pub const LC_FVMFILE: u32 = 0x9; -/// prepage command (internal use) -pub const LC_PREPAGE: u32 = 0xa; -/// dynamic link-edit symbol table info -pub const LC_DYSYMTAB: u32 = 0xb; -/// load a dynamically linked shared library -pub const LC_LOAD_DYLIB: u32 = 0xc; -/// dynamically linked shared lib ident -pub const LC_ID_DYLIB: u32 = 0xd; -/// load a dynamic linker -pub const LC_LOAD_DYLINKER: u32 = 0xe; -/// dynamic linker identification -pub const LC_ID_DYLINKER: u32 = 0xf; -/// modules prebound for a dynamically linked shared library -pub const LC_PREBOUND_DYLIB: u32 = 0x10; -/// image routines -pub const LC_ROUTINES: u32 = 0x11; -/// sub framework -pub const LC_SUB_FRAMEWORK: u32 = 0x12; -/// sub umbrella -pub const LC_SUB_UMBRELLA: u32 = 0x13; -/// sub client -pub const LC_SUB_CLIENT: u32 = 0x14; -/// sub library -pub const LC_SUB_LIBRARY: u32 = 0x15; -/// two-level namespace lookup hints -pub const LC_TWOLEVEL_HINTS: u32 = 0x16; -/// prebind checksum -pub const LC_PREBIND_CKSUM: u32 = 0x17; -/// load a dynamically linked shared library that is allowed to be missing -/// (all symbols are weak imported). -pub const LC_LOAD_WEAK_DYLIB: u32 = 0x18 | LC_REQ_DYLD; -/// 64-bit segment of this file to be mapped -pub const LC_SEGMENT_64: u32 = 0x19; -/// 64-bit image routines -pub const LC_ROUTINES_64: u32 = 0x1a; -/// the uuid -pub const LC_UUID: u32 = 0x1b; -/// runpath additions -pub const LC_RPATH: u32 = 0x1c | LC_REQ_DYLD; -/// local of code signature -pub const LC_CODE_SIGNATURE: u32 = 0x1d; -/// local of info to split segments -pub const LC_SEGMENT_SPLIT_INFO: u32 = 0x1e; -/// load and re-export dylib -pub const LC_REEXPORT_DYLIB: u32 = 0x1f | LC_REQ_DYLD; -/// delay load of dylib until first use -pub const LC_LAZY_LOAD_DYLIB: u32 = 0x20; -/// encrypted segment information -pub const LC_ENCRYPTION_INFO: u32 = 0x21; -/// compressed dyld information -pub const LC_DYLD_INFO: u32 = 0x22; -/// compressed dyld information only -pub const LC_DYLD_INFO_ONLY: u32 = 0x22 | LC_REQ_DYLD; -/// load upward dylib -pub const LC_LOAD_UPWARD_DYLIB: u32 = 0x23 | LC_REQ_DYLD; -/// build for MacOSX min OS version -pub const LC_VERSION_MIN_MACOSX: u32 = 0x24; -/// build for iPhoneOS min OS version -pub const LC_VERSION_MIN_IPHONEOS: u32 = 0x25; -/// compressed table of function start addresses -pub const LC_FUNCTION_STARTS: u32 = 0x26; -/// string for dyld to treat like environment variable -pub const LC_DYLD_ENVIRONMENT: u32 = 0x27; -/// replacement for LC_UNIXTHREAD -pub const LC_MAIN: u32 = 0x28 | LC_REQ_DYLD; -/// table of non-instructions in __text -pub const LC_DATA_IN_CODE: u32 = 0x29; -/// source version used to build binary -pub const LC_SOURCE_VERSION: u32 = 0x2A; -/// Code signing DRs copied from linked dylibs -pub const LC_DYLIB_CODE_SIGN_DRS: u32 = 0x2B; -/// 64-bit encrypted segment information -pub const LC_ENCRYPTION_INFO_64: u32 = 0x2C; -/// linker options in MH_OBJECT files -pub const LC_LINKER_OPTION: u32 = 0x2D; -/// optimization hints in MH_OBJECT files -pub const LC_LINKER_OPTIMIZATION_HINT: u32 = 0x2E; -/// build for AppleTV min OS version -pub const LC_VERSION_MIN_TVOS: u32 = 0x2F; -/// build for Watch min OS version -pub const LC_VERSION_MIN_WATCHOS: u32 = 0x30; -/// arbitrary data included within a Mach-O file -pub const LC_NOTE: u32 = 0x31; -/// build for platform min OS version -pub const LC_BUILD_VERSION: u32 = 0x32; -/// used with `LinkeditDataCommand`, payload is trie -pub const LC_DYLD_EXPORTS_TRIE: u32 = 0x33 | LC_REQ_DYLD; -/// used with `LinkeditDataCommand` -pub const LC_DYLD_CHAINED_FIXUPS: u32 = 0x34 | LC_REQ_DYLD; -/// used with `FilesetEntryCommand` -pub const LC_FILESET_ENTRY: u32 = 0x35 | LC_REQ_DYLD; - -/// A variable length string in a load command. -/// -/// The strings are stored just after the load command structure and -/// the offset is from the start of the load command structure. The size -/// of the string is reflected in the `cmdsize` field of the load command. -/// Once again any padded bytes to bring the `cmdsize` field to a multiple -/// of 4 bytes must be zero. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct LcStr { - /// offset to the string - pub offset: U32, -} - -/// 32-bit segment load command. -/// -/// The segment load command indicates that a part of this file is to be -/// mapped into the task's address space. The size of this segment in memory, -/// vmsize, maybe equal to or larger than the amount to map from this file, -/// filesize. The file is mapped starting at fileoff to the beginning of -/// the segment in memory, vmaddr. The rest of the memory of the segment, -/// if any, is allocated zero fill on demand. The segment's maximum virtual -/// memory protection and initial virtual memory protection are specified -/// by the maxprot and initprot fields. If the segment has sections then the -/// `Section32` structures directly follow the segment command and their size is -/// reflected in `cmdsize`. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SegmentCommand32 { - /// LC_SEGMENT - pub cmd: U32, - /// includes sizeof section structs - pub cmdsize: U32, - /// segment name - pub segname: [u8; 16], - /// memory address of this segment - pub vmaddr: U32, - /// memory size of this segment - pub vmsize: U32, - /// file offset of this segment - pub fileoff: U32, - /// amount to map from the file - pub filesize: U32, - /// maximum VM protection - pub maxprot: U32, - /// initial VM protection - pub initprot: U32, - /// number of sections in segment - pub nsects: U32, - /// flags - pub flags: U32, -} - -/// 64-bit segment load command. -/// -/// The 64-bit segment load command indicates that a part of this file is to be -/// mapped into a 64-bit task's address space. If the 64-bit segment has -/// sections then `Section64` structures directly follow the 64-bit segment -/// command and their size is reflected in `cmdsize`. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SegmentCommand64 { - /// LC_SEGMENT_64 - pub cmd: U32, - /// includes sizeof section_64 structs - pub cmdsize: U32, - /// segment name - pub segname: [u8; 16], - /// memory address of this segment - pub vmaddr: U64, - /// memory size of this segment - pub vmsize: U64, - /// file offset of this segment - pub fileoff: U64, - /// amount to map from the file - pub filesize: U64, - /// maximum VM protection - pub maxprot: U32, - /// initial VM protection - pub initprot: U32, - /// number of sections in segment - pub nsects: U32, - /// flags - pub flags: U32, -} - -// Values for `SegmentCommand*::flags`. -/// the file contents for this segment is for the high part of the VM space, the low part is zero filled (for stacks in core files) -pub const SG_HIGHVM: u32 = 0x1; -/// this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor -pub const SG_FVMLIB: u32 = 0x2; -/// this segment has nothing that was relocated in it and nothing relocated to it, that is it maybe safely replaced without relocation -pub const SG_NORELOC: u32 = 0x4; -/// This segment is protected. If the segment starts at file offset 0, the first page of the segment is not protected. All other pages of the segment are protected. -pub const SG_PROTECTED_VERSION_1: u32 = 0x8; -/// This segment is made read-only after fixups -pub const SG_READ_ONLY: u32 = 0x10; - -/* - * A segment is made up of zero or more sections. Non-MH_OBJECT files have - * all of their segments with the proper sections in each, and padded to the - * specified segment alignment when produced by the link editor. The first - * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header - * and load commands of the object file before its first section. The zero - * fill sections are always last in their segment (in all formats). This - * allows the zeroed segment padding to be mapped into memory where zero fill - * sections might be. The gigabyte zero fill sections, those with the section - * type S_GB_ZEROFILL, can only be in a segment with sections of this type. - * These segments are then placed after all other segments. - * - * The MH_OBJECT format has all of its sections in one segment for - * compactness. There is no padding to a specified segment boundary and the - * mach_header and load commands are not part of the segment. - * - * Sections with the same section name, sectname, going into the same segment, - * segname, are combined by the link editor. The resulting section is aligned - * to the maximum alignment of the combined sections and is the new section's - * alignment. The combined sections are aligned to their original alignment in - * the combined section. Any padded bytes to get the specified alignment are - * zeroed. - * - * The format of the relocation entries referenced by the reloff and nreloc - * fields of the section structure for mach object files is described in the - * header file . - */ -/// 32-bit section. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Section32 { - /// name of this section - pub sectname: [u8; 16], - /// segment this section goes in - pub segname: [u8; 16], - /// memory address of this section - pub addr: U32, - /// size in bytes of this section - pub size: U32, - /// file offset of this section - pub offset: U32, - /// section alignment (power of 2) - pub align: U32, - /// file offset of relocation entries - pub reloff: U32, - /// number of relocation entries - pub nreloc: U32, - /// flags (section type and attributes) - pub flags: U32, - /// reserved (for offset or index) - pub reserved1: U32, - /// reserved (for count or sizeof) - pub reserved2: U32, -} - -/// 64-bit section. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Section64 { - /// name of this section - pub sectname: [u8; 16], - /// segment this section goes in - pub segname: [u8; 16], - /// memory address of this section - pub addr: U64, - /// size in bytes of this section - pub size: U64, - /// file offset of this section - pub offset: U32, - /// section alignment (power of 2) - pub align: U32, - /// file offset of relocation entries - pub reloff: U32, - /// number of relocation entries - pub nreloc: U32, - /// flags (section type and attributes) - pub flags: U32, - /// reserved (for offset or index) - pub reserved1: U32, - /// reserved (for count or sizeof) - pub reserved2: U32, - /// reserved - pub reserved3: U32, -} - -/* - * The flags field of a section structure is separated into two parts a section - * type and section attributes. The section types are mutually exclusive (it - * can only have one type) but the section attributes are not (it may have more - * than one attribute). - */ -/// 256 section types -pub const SECTION_TYPE: u32 = 0x0000_00ff; -/// 24 section attributes -pub const SECTION_ATTRIBUTES: u32 = 0xffff_ff00; - -/* Constants for the type of a section */ -/// regular section -pub const S_REGULAR: u32 = 0x0; -/// zero fill on demand section -pub const S_ZEROFILL: u32 = 0x1; -/// section with only literal C strings -pub const S_CSTRING_LITERALS: u32 = 0x2; -/// section with only 4 byte literals -pub const S_4BYTE_LITERALS: u32 = 0x3; -/// section with only 8 byte literals -pub const S_8BYTE_LITERALS: u32 = 0x4; -/// section with only pointers to literals -pub const S_LITERAL_POINTERS: u32 = 0x5; -/* - * For the two types of symbol pointers sections and the symbol stubs section - * they have indirect symbol table entries. For each of the entries in the - * section the indirect symbol table entries, in corresponding order in the - * indirect symbol table, start at the index stored in the reserved1 field - * of the section structure. Since the indirect symbol table entries - * correspond to the entries in the section the number of indirect symbol table - * entries is inferred from the size of the section divided by the size of the - * entries in the section. For symbol pointers sections the size of the entries - * in the section is 4 bytes and for symbol stubs sections the byte size of the - * stubs is stored in the reserved2 field of the section structure. - */ -/// section with only non-lazy symbol pointers -pub const S_NON_LAZY_SYMBOL_POINTERS: u32 = 0x6; -/// section with only lazy symbol pointers -pub const S_LAZY_SYMBOL_POINTERS: u32 = 0x7; -/// section with only symbol stubs, byte size of stub in the reserved2 field -pub const S_SYMBOL_STUBS: u32 = 0x8; -/// section with only function pointers for initialization -pub const S_MOD_INIT_FUNC_POINTERS: u32 = 0x9; -/// section with only function pointers for termination -pub const S_MOD_TERM_FUNC_POINTERS: u32 = 0xa; -/// section contains symbols that are to be coalesced -pub const S_COALESCED: u32 = 0xb; -/// zero fill on demand section (that can be larger than 4 gigabytes) -pub const S_GB_ZEROFILL: u32 = 0xc; -/// section with only pairs of function pointers for interposing -pub const S_INTERPOSING: u32 = 0xd; -/// section with only 16 byte literals -pub const S_16BYTE_LITERALS: u32 = 0xe; -/// section contains DTrace Object Format -pub const S_DTRACE_DOF: u32 = 0xf; -/// section with only lazy symbol pointers to lazy loaded dylibs -pub const S_LAZY_DYLIB_SYMBOL_POINTERS: u32 = 0x10; -/* - * Section types to support thread local variables - */ -/// template of initial values for TLVs -pub const S_THREAD_LOCAL_REGULAR: u32 = 0x11; -/// template of initial values for TLVs -pub const S_THREAD_LOCAL_ZEROFILL: u32 = 0x12; -/// TLV descriptors -pub const S_THREAD_LOCAL_VARIABLES: u32 = 0x13; -/// pointers to TLV descriptors -pub const S_THREAD_LOCAL_VARIABLE_POINTERS: u32 = 0x14; -/// functions to call to initialize TLV values -pub const S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: u32 = 0x15; -/// 32-bit offsets to initializers -pub const S_INIT_FUNC_OFFSETS: u32 = 0x16; - -/* - * Constants for the section attributes part of the flags field of a section - * structure. - */ -/// User setable attributes -pub const SECTION_ATTRIBUTES_USR: u32 = 0xff00_0000; -/// section contains only true machine instructions -pub const S_ATTR_PURE_INSTRUCTIONS: u32 = 0x8000_0000; -/// section contains coalesced symbols that are not to be in a ranlib table of contents -pub const S_ATTR_NO_TOC: u32 = 0x4000_0000; -/// ok to strip static symbols in this section in files with the MH_DYLDLINK flag -pub const S_ATTR_STRIP_STATIC_SYMS: u32 = 0x2000_0000; -/// no dead stripping -pub const S_ATTR_NO_DEAD_STRIP: u32 = 0x1000_0000; -/// blocks are live if they reference live blocks -pub const S_ATTR_LIVE_SUPPORT: u32 = 0x0800_0000; -/// Used with i386 code stubs written on by dyld -pub const S_ATTR_SELF_MODIFYING_CODE: u32 = 0x0400_0000; -/* - * If a segment contains any sections marked with S_ATTR_DEBUG then all - * sections in that segment must have this attribute. No section other than - * a section marked with this attribute may reference the contents of this - * section. A section with this attribute may contain no symbols and must have - * a section type S_REGULAR. The static linker will not copy section contents - * from sections with this attribute into its output file. These sections - * generally contain DWARF debugging info. - */ -/// a debug section -pub const S_ATTR_DEBUG: u32 = 0x0200_0000; -/// system setable attributes -pub const SECTION_ATTRIBUTES_SYS: u32 = 0x00ff_ff00; -/// section contains some machine instructions -pub const S_ATTR_SOME_INSTRUCTIONS: u32 = 0x0000_0400; -/// section has external relocation entries -pub const S_ATTR_EXT_RELOC: u32 = 0x0000_0200; -/// section has local relocation entries -pub const S_ATTR_LOC_RELOC: u32 = 0x0000_0100; - -/* - * The names of segments and sections in them are mostly meaningless to the - * link-editor. But there are few things to support traditional UNIX - * executables that require the link-editor and assembler to use some names - * agreed upon by convention. - * - * The initial protection of the "__TEXT" segment has write protection turned - * off (not writeable). - * - * The link-editor will allocate common symbols at the end of the "__common" - * section in the "__DATA" segment. It will create the section and segment - * if needed. - */ - -/* The currently known segment names and the section names in those segments */ - -/// the pagezero segment which has no protections and catches NULL references for MH_EXECUTE files -pub const SEG_PAGEZERO: &str = "__PAGEZERO"; - -/// the tradition UNIX text segment -pub const SEG_TEXT: &str = "__TEXT"; -/// the real text part of the text section no headers, and no padding -pub const SECT_TEXT: &str = "__text"; -/// the fvmlib initialization section -pub const SECT_FVMLIB_INIT0: &str = "__fvmlib_init0"; -/// the section following the fvmlib initialization section -pub const SECT_FVMLIB_INIT1: &str = "__fvmlib_init1"; - -/// the tradition UNIX data segment -pub const SEG_DATA: &str = "__DATA"; -/// the real initialized data section no padding, no bss overlap -pub const SECT_DATA: &str = "__data"; -/// the real uninitialized data section no padding -pub const SECT_BSS: &str = "__bss"; -/// the section common symbols are allocated in by the link editor -pub const SECT_COMMON: &str = "__common"; - -/// objective-C runtime segment -pub const SEG_OBJC: &str = "__OBJC"; -/// symbol table -pub const SECT_OBJC_SYMBOLS: &str = "__symbol_table"; -/// module information -pub const SECT_OBJC_MODULES: &str = "__module_info"; -/// string table -pub const SECT_OBJC_STRINGS: &str = "__selector_strs"; -/// string table -pub const SECT_OBJC_REFS: &str = "__selector_refs"; - -/// the icon segment -pub const SEG_ICON: &str = "__ICON"; -/// the icon headers -pub const SECT_ICON_HEADER: &str = "__header"; -/// the icons in tiff format -pub const SECT_ICON_TIFF: &str = "__tiff"; - -/// the segment containing all structs created and maintained by the link editor. Created with -seglinkedit option to ld(1) for MH_EXECUTE and FVMLIB file types only -pub const SEG_LINKEDIT: &str = "__LINKEDIT"; - -/// the segment overlapping with linkedit containing linking information -pub const SEG_LINKINFO: &str = "__LINKINFO"; - -/// the unix stack segment -pub const SEG_UNIXSTACK: &str = "__UNIXSTACK"; - -/// the segment for the self (dyld) modifying code stubs that has read, write and execute permissions -pub const SEG_IMPORT: &str = "__IMPORT"; - -/* - * Fixed virtual memory shared libraries are identified by two things. The - * target pathname (the name of the library as found for execution), and the - * minor version number. The address of where the headers are loaded is in - * header_addr. (THIS IS OBSOLETE and no longer supported). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Fvmlib { - /// library's target pathname - pub name: LcStr, - /// library's minor version number - pub minor_version: U32, - /// library's header address - pub header_addr: U32, -} - -/* - * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header) - * contains a `FvmlibCommand` (cmd == LC_IDFVMLIB) to identify the library. - * An object that uses a fixed virtual shared library also contains a - * `FvmlibCommand` (cmd == LC_LOADFVMLIB) for each library it uses. - * (THIS IS OBSOLETE and no longer supported). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FvmlibCommand { - /// LC_IDFVMLIB or LC_LOADFVMLIB - pub cmd: U32, - /// includes pathname string - pub cmdsize: U32, - /// the library identification - pub fvmlib: Fvmlib, -} - -/* - * Dynamically linked shared libraries are identified by two things. The - * pathname (the name of the library as found for execution), and the - * compatibility version number. The pathname must match and the compatibility - * number in the user of the library must be greater than or equal to the - * library being used. The time stamp is used to record the time a library was - * built and copied into user so it can be use to determined if the library used - * at runtime is exactly the same as used to built the program. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Dylib { - /// library's path name - pub name: LcStr, - /// library's build time stamp - pub timestamp: U32, - /// library's current version number - pub current_version: U32, - /// library's compatibility vers number - pub compatibility_version: U32, -} - -/* - * A dynamically linked shared library (filetype == MH_DYLIB in the mach header) - * contains a `DylibCommand` (cmd == LC_ID_DYLIB) to identify the library. - * An object that uses a dynamically linked shared library also contains a - * `DylibCommand` (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or - * LC_REEXPORT_DYLIB) for each library it uses. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylibCommand { - /// LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, LC_REEXPORT_DYLIB - pub cmd: U32, - /// includes pathname string - pub cmdsize: U32, - /// the library identification - pub dylib: Dylib, -} - -/* - * A dynamically linked shared library may be a subframework of an umbrella - * framework. If so it will be linked with "-umbrella umbrella_name" where - * Where "umbrella_name" is the name of the umbrella framework. A subframework - * can only be linked against by its umbrella framework or other subframeworks - * that are part of the same umbrella framework. Otherwise the static link - * editor produces an error and states to link against the umbrella framework. - * The name of the umbrella framework for subframeworks is recorded in the - * following structure. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SubFrameworkCommand { - /// LC_SUB_FRAMEWORK - pub cmd: U32, - /// includes umbrella string - pub cmdsize: U32, - /// the umbrella framework name - pub umbrella: LcStr, -} - -/* - * For dynamically linked shared libraries that are subframework of an umbrella - * framework they can allow clients other than the umbrella framework or other - * subframeworks in the same umbrella framework. To do this the subframework - * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load - * command is created for each -allowable_client flag. The client_name is - * usually a framework name. It can also be a name used for bundles clients - * where the bundle is built with "-client_name client_name". - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SubClientCommand { - /// LC_SUB_CLIENT - pub cmd: U32, - /// includes client string - pub cmdsize: U32, - /// the client name - pub client: LcStr, -} - -/* - * A dynamically linked shared library may be a sub_umbrella of an umbrella - * framework. If so it will be linked with "-sub_umbrella umbrella_name" where - * Where "umbrella_name" is the name of the sub_umbrella framework. When - * statically linking when -twolevel_namespace is in effect a twolevel namespace - * umbrella framework will only cause its subframeworks and those frameworks - * listed as sub_umbrella frameworks to be implicited linked in. Any other - * dependent dynamic libraries will not be linked it when -twolevel_namespace - * is in effect. The primary library recorded by the static linker when - * resolving a symbol in these libraries will be the umbrella framework. - * Zero or more sub_umbrella frameworks may be use by an umbrella framework. - * The name of a sub_umbrella framework is recorded in the following structure. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SubUmbrellaCommand { - /// LC_SUB_UMBRELLA - pub cmd: U32, - /// includes sub_umbrella string - pub cmdsize: U32, - /// the sub_umbrella framework name - pub sub_umbrella: LcStr, -} - -/* - * A dynamically linked shared library may be a sub_library of another shared - * library. If so it will be linked with "-sub_library library_name" where - * Where "library_name" is the name of the sub_library shared library. When - * statically linking when -twolevel_namespace is in effect a twolevel namespace - * shared library will only cause its subframeworks and those frameworks - * listed as sub_umbrella frameworks and libraries listed as sub_libraries to - * be implicited linked in. Any other dependent dynamic libraries will not be - * linked it when -twolevel_namespace is in effect. The primary library - * recorded by the static linker when resolving a symbol in these libraries - * will be the umbrella framework (or dynamic library). Zero or more sub_library - * shared libraries may be use by an umbrella framework or (or dynamic library). - * The name of a sub_library framework is recorded in the following structure. - * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc". - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SubLibraryCommand { - /// LC_SUB_LIBRARY - pub cmd: U32, - /// includes sub_library string - pub cmdsize: U32, - /// the sub_library name - pub sub_library: LcStr, -} - -/* - * A program (filetype == MH_EXECUTE) that is - * prebound to its dynamic libraries has one of these for each library that - * the static linker used in prebinding. It contains a bit vector for the - * modules in the library. The bits indicate which modules are bound (1) and - * which are not (0) from the library. The bit for module 0 is the low bit - * of the first byte. So the bit for the Nth module is: - * (linked_modules[N/8] >> N%8) & 1 - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct PreboundDylibCommand { - /// LC_PREBOUND_DYLIB - pub cmd: U32, - /// includes strings - pub cmdsize: U32, - /// library's path name - pub name: LcStr, - /// number of modules in library - pub nmodules: U32, - /// bit vector of linked modules - pub linked_modules: LcStr, -} - -/* - * A program that uses a dynamic linker contains a `DylinkerCommand` to identify - * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker - * contains a `DylinkerCommand` to identify the dynamic linker (LC_ID_DYLINKER). - * A file can have at most one of these. - * This struct is also used for the LC_DYLD_ENVIRONMENT load command and - * contains string for dyld to treat like environment variable. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylinkerCommand { - /// LC_ID_DYLINKER, LC_LOAD_DYLINKER or LC_DYLD_ENVIRONMENT - pub cmd: U32, - /// includes pathname string - pub cmdsize: U32, - /// dynamic linker's path name - pub name: LcStr, -} - -/* - * Thread commands contain machine-specific data structures suitable for - * use in the thread state primitives. The machine specific data structures - * follow the struct `ThreadCommand` as follows. - * Each flavor of machine specific data structure is preceded by an uint32_t - * constant for the flavor of that data structure, an uint32_t that is the - * count of uint32_t's of the size of the state data structure and then - * the state data structure follows. This triple may be repeated for many - * flavors. The constants for the flavors, counts and state data structure - * definitions are expected to be in the header file . - * These machine specific data structures sizes must be multiples of - * 4 bytes. The `cmdsize` reflects the total size of the `ThreadCommand` - * and all of the sizes of the constants for the flavors, counts and state - * data structures. - * - * For executable objects that are unix processes there will be one - * `ThreadCommand` (cmd == LC_UNIXTHREAD) created for it by the link-editor. - * This is the same as a LC_THREAD, except that a stack is automatically - * created (based on the shell's limit for the stack size). Command arguments - * and environment variables are copied onto that stack. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ThreadCommand { - /// LC_THREAD or LC_UNIXTHREAD - pub cmd: U32, - /// total size of this command - pub cmdsize: U32, - /* uint32_t flavor flavor of thread state */ - /* uint32_t count count of uint32_t's in thread state */ - /* struct XXX_thread_state state thread state for this flavor */ - /* ... */ -} - -/* - * The routines command contains the address of the dynamic shared library - * initialization routine and an index into the module table for the module - * that defines the routine. Before any modules are used from the library the - * dynamic linker fully binds the module that defines the initialization routine - * and then calls it. This gets called before any module initialization - * routines (used for C++ static constructors) in the library. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct RoutinesCommand32 { - /* for 32-bit architectures */ - /// LC_ROUTINES - pub cmd: U32, - /// total size of this command - pub cmdsize: U32, - /// address of initialization routine - pub init_address: U32, - /// index into the module table that the init routine is defined in - pub init_module: U32, - pub reserved1: U32, - pub reserved2: U32, - pub reserved3: U32, - pub reserved4: U32, - pub reserved5: U32, - pub reserved6: U32, -} - -/* - * The 64-bit routines command. Same use as above. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct RoutinesCommand64 { - /* for 64-bit architectures */ - /// LC_ROUTINES_64 - pub cmd: U32, - /// total size of this command - pub cmdsize: U32, - /// address of initialization routine - pub init_address: U64, - /// index into the module table that the init routine is defined in - pub init_module: U64, - pub reserved1: U64, - pub reserved2: U64, - pub reserved3: U64, - pub reserved4: U64, - pub reserved5: U64, - pub reserved6: U64, -} - -/* - * The `SymtabCommand` contains the offsets and sizes of the link-edit 4.3BSD - * "stab" style symbol table information as described in the header files - * and . - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SymtabCommand { - /// LC_SYMTAB - pub cmd: U32, - /// sizeof(struct SymtabCommand) - pub cmdsize: U32, - /// symbol table offset - pub symoff: U32, - /// number of symbol table entries - pub nsyms: U32, - /// string table offset - pub stroff: U32, - /// string table size in bytes - pub strsize: U32, -} - -/* - * This is the second set of the symbolic information which is used to support - * the data structures for the dynamically link editor. - * - * The original set of symbolic information in the `SymtabCommand` which contains - * the symbol and string tables must also be present when this load command is - * present. When this load command is present the symbol table is organized - * into three groups of symbols: - * local symbols (static and debugging symbols) - grouped by module - * defined external symbols - grouped by module (sorted by name if not lib) - * undefined external symbols (sorted by name if MH_BINDATLOAD is not set, - * and in order the were seen by the static - * linker if MH_BINDATLOAD is set) - * In this load command there are offsets and counts to each of the three groups - * of symbols. - * - * This load command contains a the offsets and sizes of the following new - * symbolic information tables: - * table of contents - * module table - * reference symbol table - * indirect symbol table - * The first three tables above (the table of contents, module table and - * reference symbol table) are only present if the file is a dynamically linked - * shared library. For executable and object modules, which are files - * containing only one module, the information that would be in these three - * tables is determined as follows: - * table of contents - the defined external symbols are sorted by name - * module table - the file contains only one module so everything in the - * file is part of the module. - * reference symbol table - is the defined and undefined external symbols - * - * For dynamically linked shared library files this load command also contains - * offsets and sizes to the pool of relocation entries for all sections - * separated into two groups: - * external relocation entries - * local relocation entries - * For executable and object modules the relocation entries continue to hang - * off the section structures. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DysymtabCommand { - /// LC_DYSYMTAB - pub cmd: U32, - /// sizeof(struct DysymtabCommand) - pub cmdsize: U32, - - /* - * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command - * are grouped into the following three groups: - * local symbols (further grouped by the module they are from) - * defined external symbols (further grouped by the module they are from) - * undefined symbols - * - * The local symbols are used only for debugging. The dynamic binding - * process may have to use them to indicate to the debugger the local - * symbols for a module that is being bound. - * - * The last two groups are used by the dynamic binding process to do the - * binding (indirectly through the module table and the reference symbol - * table when this is a dynamically linked shared library file). - */ - /// index to local symbols - pub ilocalsym: U32, - /// number of local symbols - pub nlocalsym: U32, - - /// index to externally defined symbols - pub iextdefsym: U32, - /// number of externally defined symbols - pub nextdefsym: U32, - - /// index to undefined symbols - pub iundefsym: U32, - /// number of undefined symbols - pub nundefsym: U32, - - /* - * For the for the dynamic binding process to find which module a symbol - * is defined in the table of contents is used (analogous to the ranlib - * structure in an archive) which maps defined external symbols to modules - * they are defined in. This exists only in a dynamically linked shared - * library file. For executable and object modules the defined external - * symbols are sorted by name and is use as the table of contents. - */ - /// file offset to table of contents - pub tocoff: U32, - /// number of entries in table of contents - pub ntoc: U32, - - /* - * To support dynamic binding of "modules" (whole object files) the symbol - * table must reflect the modules that the file was created from. This is - * done by having a module table that has indexes and counts into the merged - * tables for each module. The module structure that these two entries - * refer to is described below. This exists only in a dynamically linked - * shared library file. For executable and object modules the file only - * contains one module so everything in the file belongs to the module. - */ - /// file offset to module table - pub modtaboff: U32, - /// number of module table entries - pub nmodtab: U32, - - /* - * To support dynamic module binding the module structure for each module - * indicates the external references (defined and undefined) each module - * makes. For each module there is an offset and a count into the - * reference symbol table for the symbols that the module references. - * This exists only in a dynamically linked shared library file. For - * executable and object modules the defined external symbols and the - * undefined external symbols indicates the external references. - */ - /// offset to referenced symbol table - pub extrefsymoff: U32, - /// number of referenced symbol table entries - pub nextrefsyms: U32, - - /* - * The sections that contain "symbol pointers" and "routine stubs" have - * indexes and (implied counts based on the size of the section and fixed - * size of the entry) into the "indirect symbol" table for each pointer - * and stub. For every section of these two types the index into the - * indirect symbol table is stored in the section header in the field - * reserved1. An indirect symbol table entry is simply a 32bit index into - * the symbol table to the symbol that the pointer or stub is referring to. - * The indirect symbol table is ordered to match the entries in the section. - */ - /// file offset to the indirect symbol table - pub indirectsymoff: U32, - /// number of indirect symbol table entries - pub nindirectsyms: U32, - - /* - * To support relocating an individual module in a library file quickly the - * external relocation entries for each module in the library need to be - * accessed efficiently. Since the relocation entries can't be accessed - * through the section headers for a library file they are separated into - * groups of local and external entries further grouped by module. In this - * case the presents of this load command who's extreloff, nextrel, - * locreloff and nlocrel fields are non-zero indicates that the relocation - * entries of non-merged sections are not referenced through the section - * structures (and the reloff and nreloc fields in the section headers are - * set to zero). - * - * Since the relocation entries are not accessed through the section headers - * this requires the r_address field to be something other than a section - * offset to identify the item to be relocated. In this case r_address is - * set to the offset from the vmaddr of the first LC_SEGMENT command. - * For MH_SPLIT_SEGS images r_address is set to the the offset from the - * vmaddr of the first read-write LC_SEGMENT command. - * - * The relocation entries are grouped by module and the module table - * entries have indexes and counts into them for the group of external - * relocation entries for that the module. - * - * For sections that are merged across modules there must not be any - * remaining external relocation entries for them (for merged sections - * remaining relocation entries must be local). - */ - /// offset to external relocation entries - pub extreloff: U32, - /// number of external relocation entries - pub nextrel: U32, - - /* - * All the local relocation entries are grouped together (they are not - * grouped by their module since they are only used if the object is moved - * from it statically link edited address). - */ - /// offset to local relocation entries - pub locreloff: U32, - /// number of local relocation entries - pub nlocrel: U32, -} - -/* - * An indirect symbol table entry is simply a 32bit index into the symbol table - * to the symbol that the pointer or stub is referring to. Unless it is for a - * non-lazy symbol pointer section for a defined symbol which strip(1) as - * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the - * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. - */ -pub const INDIRECT_SYMBOL_LOCAL: u32 = 0x8000_0000; -pub const INDIRECT_SYMBOL_ABS: u32 = 0x4000_0000; - -/* a table of contents entry */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylibTableOfContents { - /// the defined external symbol (index into the symbol table) - pub symbol_index: U32, - /// index into the module table this symbol is defined in - pub module_index: U32, -} - -/* a module table entry */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylibModule32 { - /// the module name (index into string table) - pub module_name: U32, - - /// index into externally defined symbols - pub iextdefsym: U32, - /// number of externally defined symbols - pub nextdefsym: U32, - /// index into reference symbol table - pub irefsym: U32, - /// number of reference symbol table entries - pub nrefsym: U32, - /// index into symbols for local symbols - pub ilocalsym: U32, - /// number of local symbols - pub nlocalsym: U32, - - /// index into external relocation entries - pub iextrel: U32, - /// number of external relocation entries - pub nextrel: U32, - - /// low 16 bits are the index into the init section, high 16 bits are the index into the term section - pub iinit_iterm: U32, - /// low 16 bits are the number of init section entries, high 16 bits are the number of term section entries - pub ninit_nterm: U32, - - /// for this module address of the start of the (__OBJC,__module_info) section - pub objc_module_info_addr: U32, - /// for this module size of the (__OBJC,__module_info) section - pub objc_module_info_size: U32, -} - -/* a 64-bit module table entry */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylibModule64 { - /// the module name (index into string table) - pub module_name: U32, - - /// index into externally defined symbols - pub iextdefsym: U32, - /// number of externally defined symbols - pub nextdefsym: U32, - /// index into reference symbol table - pub irefsym: U32, - /// number of reference symbol table entries - pub nrefsym: U32, - /// index into symbols for local symbols - pub ilocalsym: U32, - /// number of local symbols - pub nlocalsym: U32, - - /// index into external relocation entries - pub iextrel: U32, - /// number of external relocation entries - pub nextrel: U32, - - /// low 16 bits are the index into the init section, high 16 bits are the index into the term section - pub iinit_iterm: U32, - /// low 16 bits are the number of init section entries, high 16 bits are the number of term section entries - pub ninit_nterm: U32, - - /// for this module size of the (__OBJC,__module_info) section - pub objc_module_info_size: U32, - /// for this module address of the start of the (__OBJC,__module_info) section - pub objc_module_info_addr: U64, -} - -/* - * The entries in the reference symbol table are used when loading the module - * (both by the static and dynamic link editors) and if the module is unloaded - * or replaced. Therefore all external symbols (defined and undefined) are - * listed in the module's reference table. The flags describe the type of - * reference that is being made. The constants for the flags are defined in - * as they are also used for symbol table entries. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DylibReference { - /* TODO: - uint32_t isym:24, /* index into the symbol table */ - flags:8; /* flags to indicate the type of reference */ - */ - pub bitfield: U32, -} - -/* - * The TwolevelHintsCommand contains the offset and number of hints in the - * two-level namespace lookup hints table. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct TwolevelHintsCommand { - /// LC_TWOLEVEL_HINTS - pub cmd: U32, - /// sizeof(struct TwolevelHintsCommand) - pub cmdsize: U32, - /// offset to the hint table - pub offset: U32, - /// number of hints in the hint table - pub nhints: U32, -} - -/* - * The entries in the two-level namespace lookup hints table are TwolevelHint - * structs. These provide hints to the dynamic link editor where to start - * looking for an undefined symbol in a two-level namespace image. The - * isub_image field is an index into the sub-images (sub-frameworks and - * sub-umbrellas list) that made up the two-level image that the undefined - * symbol was found in when it was built by the static link editor. If - * isub-image is 0 the the symbol is expected to be defined in library and not - * in the sub-images. If isub-image is non-zero it is an index into the array - * of sub-images for the umbrella with the first index in the sub-images being - * 1. The array of sub-images is the ordered list of sub-images of the umbrella - * that would be searched for a symbol that has the umbrella recorded as its - * primary library. The table of contents index is an index into the - * library's table of contents. This is used as the starting point of the - * binary search or a directed linear search. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct TwolevelHint { - /* TODO: - uint32_t - isub_image:8, /* index into the sub images */ - itoc:24; /* index into the table of contents */ - */ - pub bitfield: U32, -} - -/* - * The PrebindCksumCommand contains the value of the original check sum for - * prebound files or zero. When a prebound file is first created or modified - * for other than updating its prebinding information the value of the check sum - * is set to zero. When the file has it prebinding re-done and if the value of - * the check sum is zero the original check sum is calculated and stored in - * cksum field of this load command in the output file. If when the prebinding - * is re-done and the cksum field is non-zero it is left unchanged from the - * input file. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct PrebindCksumCommand { - /// LC_PREBIND_CKSUM - pub cmd: U32, - /// sizeof(struct PrebindCksumCommand) - pub cmdsize: U32, - /// the check sum or zero - pub cksum: U32, -} - -/* - * The uuid load command contains a single 128-bit unique random number that - * identifies an object produced by the static link editor. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct UuidCommand { - /// LC_UUID - pub cmd: U32, - /// sizeof(struct UuidCommand) - pub cmdsize: U32, - /// the 128-bit uuid - pub uuid: [u8; 16], -} - -/* - * The RpathCommand contains a path which at runtime should be added to - * the current run path used to find @rpath prefixed dylibs. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct RpathCommand { - /// LC_RPATH - pub cmd: U32, - /// includes string - pub cmdsize: U32, - /// path to add to run path - pub path: LcStr, -} - -/* - * The LinkeditDataCommand contains the offsets and sizes of a blob - * of data in the __LINKEDIT segment. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct LinkeditDataCommand { - /// `LC_CODE_SIGNATURE`, `LC_SEGMENT_SPLIT_INFO`, `LC_FUNCTION_STARTS`, - /// `LC_DATA_IN_CODE`, `LC_DYLIB_CODE_SIGN_DRS`, `LC_LINKER_OPTIMIZATION_HINT`, - /// `LC_DYLD_EXPORTS_TRIE`, or `LC_DYLD_CHAINED_FIXUPS`. - pub cmd: U32, - /// sizeof(struct LinkeditDataCommand) - pub cmdsize: U32, - /// file offset of data in __LINKEDIT segment - pub dataoff: U32, - /// file size of data in __LINKEDIT segment - pub datasize: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FilesetEntryCommand { - // LC_FILESET_ENTRY - pub cmd: U32, - /// includes id string - pub cmdsize: U32, - /// memory address of the dylib - pub vmaddr: U64, - /// file offset of the dylib - pub fileoff: U64, - /// contained entry id - pub entry_id: LcStr, - /// entry_id is 32-bits long, so this is the reserved padding - pub reserved: U32, -} - -/* - * The EncryptionInfoCommand32 contains the file offset and size of an - * of an encrypted segment. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct EncryptionInfoCommand32 { - /// LC_ENCRYPTION_INFO - pub cmd: U32, - /// sizeof(struct EncryptionInfoCommand32) - pub cmdsize: U32, - /// file offset of encrypted range - pub cryptoff: U32, - /// file size of encrypted range - pub cryptsize: U32, - /// which enryption system, 0 means not-encrypted yet - pub cryptid: U32, -} - -/* - * The EncryptionInfoCommand64 contains the file offset and size of an - * of an encrypted segment (for use in x86_64 targets). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct EncryptionInfoCommand64 { - /// LC_ENCRYPTION_INFO_64 - pub cmd: U32, - /// sizeof(struct EncryptionInfoCommand64) - pub cmdsize: U32, - /// file offset of encrypted range - pub cryptoff: U32, - /// file size of encrypted range - pub cryptsize: U32, - /// which enryption system, 0 means not-encrypted yet - pub cryptid: U32, - /// padding to make this struct's size a multiple of 8 bytes - pub pad: U32, -} - -/* - * The VersionMinCommand contains the min OS version on which this - * binary was built to run. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct VersionMinCommand { - /// LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_WATCHOS or LC_VERSION_MIN_TVOS - pub cmd: U32, - /// sizeof(struct VersionMinCommand) - pub cmdsize: U32, - /// X.Y.Z is encoded in nibbles xxxx.yy.zz - pub version: U32, - /// X.Y.Z is encoded in nibbles xxxx.yy.zz - pub sdk: U32, -} - -/* - * The BuildVersionCommand contains the min OS version on which this - * binary was built to run for its platform. The list of known platforms and - * tool values following it. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct BuildVersionCommand { - /// LC_BUILD_VERSION - pub cmd: U32, - /// sizeof(struct BuildVersionCommand) plus ntools * sizeof(struct BuildToolVersion) - pub cmdsize: U32, - /// platform - pub platform: U32, - /// X.Y.Z is encoded in nibbles xxxx.yy.zz - pub minos: U32, - /// X.Y.Z is encoded in nibbles xxxx.yy.zz - pub sdk: U32, - /// number of tool entries following this - pub ntools: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct BuildToolVersion { - /// enum for the tool - pub tool: U32, - /// version number of the tool - pub version: U32, -} - -/* Known values for the platform field above. */ -pub const PLATFORM_MACOS: u32 = 1; -pub const PLATFORM_IOS: u32 = 2; -pub const PLATFORM_TVOS: u32 = 3; -pub const PLATFORM_WATCHOS: u32 = 4; -pub const PLATFORM_BRIDGEOS: u32 = 5; -pub const PLATFORM_MACCATALYST: u32 = 6; -pub const PLATFORM_IOSSIMULATOR: u32 = 7; -pub const PLATFORM_TVOSSIMULATOR: u32 = 8; -pub const PLATFORM_WATCHOSSIMULATOR: u32 = 9; -pub const PLATFORM_DRIVERKIT: u32 = 10; - -/* Known values for the tool field above. */ -pub const TOOL_CLANG: u32 = 1; -pub const TOOL_SWIFT: u32 = 2; -pub const TOOL_LD: u32 = 3; - -/* - * The DyldInfoCommand contains the file offsets and sizes of - * the new compressed form of the information dyld needs to - * load the image. This information is used by dyld on Mac OS X - * 10.6 and later. All information pointed to by this command - * is encoded using byte streams, so no endian swapping is needed - * to interpret it. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DyldInfoCommand { - /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY - pub cmd: U32, - /// sizeof(struct DyldInfoCommand) - pub cmdsize: U32, - - /* - * Dyld rebases an image whenever dyld loads it at an address different - * from its preferred address. The rebase information is a stream - * of byte sized opcodes whose symbolic names start with REBASE_OPCODE_. - * Conceptually the rebase information is a table of tuples: - * - * The opcodes are a compressed way to encode the table by only - * encoding when a column changes. In addition simple patterns - * like "every n'th offset for m times" can be encoded in a few - * bytes. - */ - /// file offset to rebase info - pub rebase_off: U32, - /// size of rebase info - pub rebase_size: U32, - - /* - * Dyld binds an image during the loading process, if the image - * requires any pointers to be initialized to symbols in other images. - * The bind information is a stream of byte sized - * opcodes whose symbolic names start with BIND_OPCODE_. - * Conceptually the bind information is a table of tuples: - * - * The opcodes are a compressed way to encode the table by only - * encoding when a column changes. In addition simple patterns - * like for runs of pointers initialized to the same value can be - * encoded in a few bytes. - */ - /// file offset to binding info - pub bind_off: U32, - /// size of binding info - pub bind_size: U32, - - /* - * Some C++ programs require dyld to unique symbols so that all - * images in the process use the same copy of some code/data. - * This step is done after binding. The content of the weak_bind - * info is an opcode stream like the bind_info. But it is sorted - * alphabetically by symbol name. This enable dyld to walk - * all images with weak binding information in order and look - * for collisions. If there are no collisions, dyld does - * no updating. That means that some fixups are also encoded - * in the bind_info. For instance, all calls to "operator new" - * are first bound to libstdc++.dylib using the information - * in bind_info. Then if some image overrides operator new - * that is detected when the weak_bind information is processed - * and the call to operator new is then rebound. - */ - /// file offset to weak binding info - pub weak_bind_off: U32, - /// size of weak binding info - pub weak_bind_size: U32, - - /* - * Some uses of external symbols do not need to be bound immediately. - * Instead they can be lazily bound on first use. The lazy_bind - * are contains a stream of BIND opcodes to bind all lazy symbols. - * Normal use is that dyld ignores the lazy_bind section when - * loading an image. Instead the static linker arranged for the - * lazy pointer to initially point to a helper function which - * pushes the offset into the lazy_bind area for the symbol - * needing to be bound, then jumps to dyld which simply adds - * the offset to lazy_bind_off to get the information on what - * to bind. - */ - /// file offset to lazy binding info - pub lazy_bind_off: U32, - /// size of lazy binding infs - pub lazy_bind_size: U32, - - /* - * The symbols exported by a dylib are encoded in a trie. This - * is a compact representation that factors out common prefixes. - * It also reduces LINKEDIT pages in RAM because it encodes all - * information (name, address, flags) in one small, contiguous range. - * The export area is a stream of nodes. The first node sequentially - * is the start node for the trie. - * - * Nodes for a symbol start with a uleb128 that is the length of - * the exported symbol information for the string so far. - * If there is no exported symbol, the node starts with a zero byte. - * If there is exported info, it follows the length. - * - * First is a uleb128 containing flags. Normally, it is followed by - * a uleb128 encoded offset which is location of the content named - * by the symbol from the mach_header for the image. If the flags - * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is - * a uleb128 encoded library ordinal, then a zero terminated - * UTF8 string. If the string is zero length, then the symbol - * is re-export from the specified dylib with the same name. - * If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following - * the flags is two uleb128s: the stub offset and the resolver offset. - * The stub is used by non-lazy pointers. The resolver is used - * by lazy pointers and must be called to get the actual address to use. - * - * After the optional exported symbol information is a byte of - * how many edges (0-255) that this node has leaving it, - * followed by each edge. - * Each edge is a zero terminated UTF8 of the addition chars - * in the symbol, followed by a uleb128 offset for the node that - * edge points to. - * - */ - /// file offset to lazy binding info - pub export_off: U32, - /// size of lazy binding infs - pub export_size: U32, -} - -/* - * The following are used to encode rebasing information - */ -pub const REBASE_TYPE_POINTER: u8 = 1; -pub const REBASE_TYPE_TEXT_ABSOLUTE32: u8 = 2; -pub const REBASE_TYPE_TEXT_PCREL32: u8 = 3; - -pub const REBASE_OPCODE_MASK: u8 = 0xF0; -pub const REBASE_IMMEDIATE_MASK: u8 = 0x0F; -pub const REBASE_OPCODE_DONE: u8 = 0x00; -pub const REBASE_OPCODE_SET_TYPE_IMM: u8 = 0x10; -pub const REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: u8 = 0x20; -pub const REBASE_OPCODE_ADD_ADDR_ULEB: u8 = 0x30; -pub const REBASE_OPCODE_ADD_ADDR_IMM_SCALED: u8 = 0x40; -pub const REBASE_OPCODE_DO_REBASE_IMM_TIMES: u8 = 0x50; -pub const REBASE_OPCODE_DO_REBASE_ULEB_TIMES: u8 = 0x60; -pub const REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: u8 = 0x70; -pub const REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: u8 = 0x80; - -/* - * The following are used to encode binding information - */ -pub const BIND_TYPE_POINTER: u8 = 1; -pub const BIND_TYPE_TEXT_ABSOLUTE32: u8 = 2; -pub const BIND_TYPE_TEXT_PCREL32: u8 = 3; - -pub const BIND_SPECIAL_DYLIB_SELF: i8 = 0; -pub const BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE: i8 = -1; -pub const BIND_SPECIAL_DYLIB_FLAT_LOOKUP: i8 = -2; -pub const BIND_SPECIAL_DYLIB_WEAK_LOOKUP: i8 = -3; - -pub const BIND_SYMBOL_FLAGS_WEAK_IMPORT: u8 = 0x1; -pub const BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION: u8 = 0x8; - -pub const BIND_OPCODE_MASK: u8 = 0xF0; -pub const BIND_IMMEDIATE_MASK: u8 = 0x0F; -pub const BIND_OPCODE_DONE: u8 = 0x00; -pub const BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: u8 = 0x10; -pub const BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: u8 = 0x20; -pub const BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: u8 = 0x30; -pub const BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: u8 = 0x40; -pub const BIND_OPCODE_SET_TYPE_IMM: u8 = 0x50; -pub const BIND_OPCODE_SET_ADDEND_SLEB: u8 = 0x60; -pub const BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: u8 = 0x70; -pub const BIND_OPCODE_ADD_ADDR_ULEB: u8 = 0x80; -pub const BIND_OPCODE_DO_BIND: u8 = 0x90; -pub const BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: u8 = 0xA0; -pub const BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: u8 = 0xB0; -pub const BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: u8 = 0xC0; -pub const BIND_OPCODE_THREADED: u8 = 0xD0; -pub const BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: u8 = 0x00; -pub const BIND_SUBOPCODE_THREADED_APPLY: u8 = 0x01; - -/* - * The following are used on the flags byte of a terminal node - * in the export information. - */ -pub const EXPORT_SYMBOL_FLAGS_KIND_MASK: u32 = 0x03; -pub const EXPORT_SYMBOL_FLAGS_KIND_REGULAR: u32 = 0x00; -pub const EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL: u32 = 0x01; -pub const EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE: u32 = 0x02; -pub const EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION: u32 = 0x04; -pub const EXPORT_SYMBOL_FLAGS_REEXPORT: u32 = 0x08; -pub const EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER: u32 = 0x10; - -/* - * The LinkerOptionCommand contains linker options embedded in object files. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct LinkerOptionCommand { - /// LC_LINKER_OPTION only used in MH_OBJECT filetypes - pub cmd: U32, - pub cmdsize: U32, - /// number of strings - pub count: U32, - /* concatenation of zero terminated UTF8 strings. - Zero filled at end to align */ -} - -/* - * The SymsegCommand contains the offset and size of the GNU style - * symbol table information as described in the header file . - * The symbol roots of the symbol segments must also be aligned properly - * in the file. So the requirement of keeping the offsets aligned to a - * multiple of a 4 bytes translates to the length field of the symbol - * roots also being a multiple of a long. Also the padding must again be - * zeroed. (THIS IS OBSOLETE and no longer supported). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SymsegCommand { - /// LC_SYMSEG - pub cmd: U32, - /// sizeof(struct SymsegCommand) - pub cmdsize: U32, - /// symbol segment offset - pub offset: U32, - /// symbol segment size in bytes - pub size: U32, -} - -/* - * The IdentCommand contains a free format string table following the - * IdentCommand structure. The strings are null terminated and the size of - * the command is padded out with zero bytes to a multiple of 4 bytes/ - * (THIS IS OBSOLETE and no longer supported). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct IdentCommand { - /// LC_IDENT - pub cmd: U32, - /// strings that follow this command - pub cmdsize: U32, -} - -/* - * The FvmfileCommand contains a reference to a file to be loaded at the - * specified virtual address. (Presently, this command is reserved for - * internal use. The kernel ignores this command when loading a program into - * memory). - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FvmfileCommand { - /// LC_FVMFILE - pub cmd: U32, - /// includes pathname string - pub cmdsize: U32, - /// files pathname - pub name: LcStr, - /// files virtual address - pub header_addr: U32, -} - -/* - * The EntryPointCommand is a replacement for thread_command. - * It is used for main executables to specify the location (file offset) - * of main(). If -stack_size was used at link time, the stacksize - * field will contain the stack size need for the main thread. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct EntryPointCommand { - /// LC_MAIN only used in MH_EXECUTE filetypes - pub cmd: U32, - /// 24 - pub cmdsize: U32, - /// file (__TEXT) offset of main() - pub entryoff: U64, - /// if not zero, initial stack size - pub stacksize: U64, -} - -/* - * The SourceVersionCommand is an optional load command containing - * the version of the sources used to build the binary. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SourceVersionCommand { - /// LC_SOURCE_VERSION - pub cmd: U32, - /// 16 - pub cmdsize: U32, - /// A.B.C.D.E packed as a24.b10.c10.d10.e10 - pub version: U64, -} - -/* - * The LC_DATA_IN_CODE load commands uses a LinkeditDataCommand - * to point to an array of DataInCodeEntry entries. Each entry - * describes a range of data in a code section. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DataInCodeEntry { - /// from mach_header to start of data range - pub offset: U32, - /// number of bytes in data range - pub length: U16, - /// a DICE_KIND_* value - pub kind: U16, -} -pub const DICE_KIND_DATA: u32 = 0x0001; -pub const DICE_KIND_JUMP_TABLE8: u32 = 0x0002; -pub const DICE_KIND_JUMP_TABLE16: u32 = 0x0003; -pub const DICE_KIND_JUMP_TABLE32: u32 = 0x0004; -pub const DICE_KIND_ABS_JUMP_TABLE32: u32 = 0x0005; - -/* - * Sections of type S_THREAD_LOCAL_VARIABLES contain an array - * of TlvDescriptor structures. - */ -/* TODO: -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct TlvDescriptor -{ - void* (*thunk)(struct TlvDescriptor*); - unsigned long key; - unsigned long offset; -} -*/ - -/* - * LC_NOTE commands describe a region of arbitrary data included in a Mach-O - * file. Its initial use is to record extra data in MH_CORE files. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct NoteCommand { - /// LC_NOTE - pub cmd: U32, - /// sizeof(struct NoteCommand) - pub cmdsize: U32, - /// owner name for this LC_NOTE - pub data_owner: [u8; 16], - /// file offset of this data - pub offset: U64, - /// length of data region - pub size: U64, -} - -// Definitions from "/usr/include/mach-o/nlist.h". - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Nlist32 { - /// index into the string table - pub n_strx: U32, - /// type flag, see below - pub n_type: u8, - /// section number or NO_SECT - pub n_sect: u8, - /// see - pub n_desc: U16, - /// value of this symbol (or stab offset) - pub n_value: U32, -} - -/* - * This is the symbol table entry structure for 64-bit architectures. - */ -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Nlist64 { - /// index into the string table - pub n_strx: U32, - /// type flag, see below - pub n_type: u8, - /// section number or NO_SECT - pub n_sect: u8, - /// see - pub n_desc: U16, - /// value of this symbol (or stab offset) - // Note: 4 byte alignment has been observed in practice. - pub n_value: U64Bytes, -} - -/* - * Symbols with a index into the string table of zero (n_un.n_strx == 0) are - * defined to have a null, "", name. Therefore all string indexes to non null - * names must not have a zero string index. This is bit historical information - * that has never been well documented. - */ - -/* - * The n_type field really contains four fields: - * unsigned char N_STAB:3, - * N_PEXT:1, - * N_TYPE:3, - * N_EXT:1; - * which are used via the following masks. - */ -/// if any of these bits set, a symbolic debugging entry -pub const N_STAB: u8 = 0xe0; -/// private external symbol bit -pub const N_PEXT: u8 = 0x10; -/// mask for the type bits -pub const N_TYPE: u8 = 0x0e; -/// external symbol bit, set for external symbols -pub const N_EXT: u8 = 0x01; - -/* - * Only symbolic debugging entries have some of the N_STAB bits set and if any - * of these bits are set then it is a symbolic debugging entry (a stab). In - * which case then the values of the n_type field (the entire field) are given - * in - */ - -/* - * Values for N_TYPE bits of the n_type field. - */ -/// undefined, n_sect == NO_SECT -pub const N_UNDF: u8 = 0x0; -/// absolute, n_sect == NO_SECT -pub const N_ABS: u8 = 0x2; -/// defined in section number n_sect -pub const N_SECT: u8 = 0xe; -/// prebound undefined (defined in a dylib) -pub const N_PBUD: u8 = 0xc; -/// indirect -pub const N_INDR: u8 = 0xa; - -/* - * If the type is N_INDR then the symbol is defined to be the same as another - * symbol. In this case the n_value field is an index into the string table - * of the other symbol's name. When the other symbol is defined then they both - * take on the defined type and value. - */ - -/* - * If the type is N_SECT then the n_sect field contains an ordinal of the - * section the symbol is defined in. The sections are numbered from 1 and - * refer to sections in order they appear in the load commands for the file - * they are in. This means the same ordinal may very well refer to different - * sections in different files. - * - * The n_value field for all symbol table entries (including N_STAB's) gets - * updated by the link editor based on the value of it's n_sect field and where - * the section n_sect references gets relocated. If the value of the n_sect - * field is NO_SECT then it's n_value field is not changed by the link editor. - */ -/// symbol is not in any section -pub const NO_SECT: u8 = 0; -/// 1 thru 255 inclusive -pub const MAX_SECT: u8 = 255; - -/* - * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types - * who's values (n_value) are non-zero. In which case the value of the n_value - * field is the size (in bytes) of the common symbol. The n_sect field is set - * to NO_SECT. The alignment of a common symbol may be set as a power of 2 - * between 2^1 and 2^15 as part of the n_desc field using the macros below. If - * the alignment is not set (a value of zero) then natural alignment based on - * the size is used. - */ -/* TODO: -#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f) -#define SET_COMM_ALIGN(n_desc,align) \ - (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8)) - */ - -/* - * To support the lazy binding of undefined symbols in the dynamic link-editor, - * the undefined symbols in the symbol table (the nlist structures) are marked - * with the indication if the undefined reference is a lazy reference or - * non-lazy reference. If both a non-lazy reference and a lazy reference is - * made to the same symbol the non-lazy reference takes precedence. A reference - * is lazy only when all references to that symbol are made through a symbol - * pointer in a lazy symbol pointer section. - * - * The implementation of marking nlist structures in the symbol table for - * undefined symbols will be to use some of the bits of the n_desc field as a - * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field - * of an nlist structure for an undefined symbol to determine the type of - * undefined reference (lazy or non-lazy). - * - * The constants for the REFERENCE FLAGS are propagated to the reference table - * in a shared library file. In that case the constant for a defined symbol, - * REFERENCE_FLAG_DEFINED, is also used. - */ -/* Reference type bits of the n_desc field of undefined symbols */ -pub const REFERENCE_TYPE: u16 = 0x7; -/* types of references */ -pub const REFERENCE_FLAG_UNDEFINED_NON_LAZY: u16 = 0; -pub const REFERENCE_FLAG_UNDEFINED_LAZY: u16 = 1; -pub const REFERENCE_FLAG_DEFINED: u16 = 2; -pub const REFERENCE_FLAG_PRIVATE_DEFINED: u16 = 3; -pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: u16 = 4; -pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: u16 = 5; - -/* - * To simplify stripping of objects that use are used with the dynamic link - * editor, the static link editor marks the symbols defined an object that are - * referenced by a dynamically bound object (dynamic shared libraries, bundles). - * With this marking strip knows not to strip these symbols. - */ -pub const REFERENCED_DYNAMICALLY: u16 = 0x0010; - -/* - * For images created by the static link editor with the -twolevel_namespace - * option in effect the flags field of the mach header is marked with - * MH_TWOLEVEL. And the binding of the undefined references of the image are - * determined by the static link editor. Which library an undefined symbol is - * bound to is recorded by the static linker in the high 8 bits of the n_desc - * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded - * references the libraries listed in the Mach-O's LC_LOAD_DYLIB, - * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and - * LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the - * headers. The library ordinals start from 1. - * For a dynamic library that is built as a two-level namespace image the - * undefined references from module defined in another use the same nlist struct - * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For - * defined symbols in all images they also must have the library ordinal set to - * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable - * image for references from plugins that refer to the executable that loads - * them. - * - * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace - * image that are looked up by the dynamic linker with flat namespace semantics. - * This ordinal was added as a feature in Mac OS X 10.3 by reducing the - * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries - * or binaries built with older tools to have 0xfe (254) dynamic libraries. In - * this case the ordinal value 0xfe (254) must be treated as a library ordinal - * for compatibility. - */ -/* TODO: -#define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff) -#define SET_LIBRARY_ORDINAL(n_desc,ordinal) \ - (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)) - */ -pub const SELF_LIBRARY_ORDINAL: u8 = 0x0; -pub const MAX_LIBRARY_ORDINAL: u8 = 0xfd; -pub const DYNAMIC_LOOKUP_ORDINAL: u8 = 0xfe; -pub const EXECUTABLE_ORDINAL: u8 = 0xff; - -/* - * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes - * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. - */ - -/* - * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a - * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the - * static link editor it is never to dead strip the symbol. - */ -/// symbol is not to be dead stripped -pub const N_NO_DEAD_STRIP: u16 = 0x0020; - -/* - * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. - * But is used in very rare cases by the dynamic link editor to mark an in - * memory symbol as discared and longer used for linking. - */ -/// symbol is discarded -pub const N_DESC_DISCARDED: u16 = 0x0020; - -/* - * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that - * the undefined symbol is allowed to be missing and is to have the address of - * zero when missing. - */ -/// symbol is weak referenced -pub const N_WEAK_REF: u16 = 0x0040; - -/* - * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic - * linkers that the symbol definition is weak, allowing a non-weak symbol to - * also be used which causes the weak definition to be discared. Currently this - * is only supported for symbols in coalesced sections. - */ -/// coalesced symbol is a weak definition -pub const N_WEAK_DEF: u16 = 0x0080; - -/* - * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker - * that the undefined symbol should be resolved using flat namespace searching. - */ -/// reference to a weak symbol -pub const N_REF_TO_WEAK: u16 = 0x0080; - -/* - * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is - * a definition of a Thumb function. - */ -/// symbol is a Thumb function (ARM) -pub const N_ARM_THUMB_DEF: u16 = 0x0008; - -/* - * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the - * that the function is actually a resolver function and should - * be called to get the address of the real function to use. - * This bit is only available in .o files (MH_OBJECT filetype) - */ -pub const N_SYMBOL_RESOLVER: u16 = 0x0100; - -/* - * The N_ALT_ENTRY bit of the n_desc field indicates that the - * symbol is pinned to the previous content. - */ -pub const N_ALT_ENTRY: u16 = 0x0200; - -// Definitions from "/usr/include/mach-o/stab.h". - -/* - * This file gives definitions supplementing for permanent symbol - * table entries of Mach-O files. Modified from the BSD definitions. The - * modifications from the original definitions were changing what the values of - * what was the n_other field (an unused field) which is now the n_sect field. - * These modifications are required to support symbols in an arbitrary number of - * sections not just the three sections (text, data and bss) in a BSD file. - * The values of the defined constants have NOT been changed. - * - * These must have one of the N_STAB bits on. The n_value fields are subject - * to relocation according to the value of their n_sect field. So for types - * that refer to things in sections the n_sect field must be filled in with the - * proper section ordinal. For types that are not to have their n_value field - * relocatated the n_sect field must be NO_SECT. - */ - -/* - * Symbolic debugger symbols. The comments give the conventional use for - * - * .stabs "n_name", n_type, n_sect, n_desc, n_value - * - * where n_type is the defined constant and not listed in the comment. Other - * fields not listed are zero. n_sect is the section ordinal the entry is - * referring to. - */ -/// global symbol: name,,NO_SECT,type,0 -pub const N_GSYM: u8 = 0x20; -/// procedure name (f77 kludge): name,,NO_SECT,0,0 -pub const N_FNAME: u8 = 0x22; -/// procedure: name,,n_sect,linenumber,address -pub const N_FUN: u8 = 0x24; -/// static symbol: name,,n_sect,type,address -pub const N_STSYM: u8 = 0x26; -/// .lcomm symbol: name,,n_sect,type,address -pub const N_LCSYM: u8 = 0x28; -/// begin nsect sym: 0,,n_sect,0,address -pub const N_BNSYM: u8 = 0x2e; -/// AST file path: name,,NO_SECT,0,0 -pub const N_AST: u8 = 0x32; -/// emitted with gcc2_compiled and in gcc source -pub const N_OPT: u8 = 0x3c; -/// register sym: name,,NO_SECT,type,register -pub const N_RSYM: u8 = 0x40; -/// src line: 0,,n_sect,linenumber,address -pub const N_SLINE: u8 = 0x44; -/// end nsect sym: 0,,n_sect,0,address -pub const N_ENSYM: u8 = 0x4e; -/// structure elt: name,,NO_SECT,type,struct_offset -pub const N_SSYM: u8 = 0x60; -/// source file name: name,,n_sect,0,address -pub const N_SO: u8 = 0x64; -/// object file name: name,,0,0,st_mtime -pub const N_OSO: u8 = 0x66; -/// local sym: name,,NO_SECT,type,offset -pub const N_LSYM: u8 = 0x80; -/// include file beginning: name,,NO_SECT,0,sum -pub const N_BINCL: u8 = 0x82; -/// #included file name: name,,n_sect,0,address -pub const N_SOL: u8 = 0x84; -/// compiler parameters: name,,NO_SECT,0,0 -pub const N_PARAMS: u8 = 0x86; -/// compiler version: name,,NO_SECT,0,0 -pub const N_VERSION: u8 = 0x88; -/// compiler -O level: name,,NO_SECT,0,0 -pub const N_OLEVEL: u8 = 0x8A; -/// parameter: name,,NO_SECT,type,offset -pub const N_PSYM: u8 = 0xa0; -/// include file end: name,,NO_SECT,0,0 -pub const N_EINCL: u8 = 0xa2; -/// alternate entry: name,,n_sect,linenumber,address -pub const N_ENTRY: u8 = 0xa4; -/// left bracket: 0,,NO_SECT,nesting level,address -pub const N_LBRAC: u8 = 0xc0; -/// deleted include file: name,,NO_SECT,0,sum -pub const N_EXCL: u8 = 0xc2; -/// right bracket: 0,,NO_SECT,nesting level,address -pub const N_RBRAC: u8 = 0xe0; -/// begin common: name,,NO_SECT,0,0 -pub const N_BCOMM: u8 = 0xe2; -/// end common: name,,n_sect,0,0 -pub const N_ECOMM: u8 = 0xe4; -/// end common (local name): 0,,n_sect,0,address -pub const N_ECOML: u8 = 0xe8; -/// second stab entry with length information -pub const N_LENG: u8 = 0xfe; - -/* - * for the berkeley pascal compiler, pc(1): - */ -/// global pascal symbol: name,,NO_SECT,subtype,line -pub const N_PC: u8 = 0x30; - -// Definitions from "/usr/include/mach-o/reloc.h". - -/// A relocation entry. -/// -/// Mach-O relocations have plain and scattered variants, with the -/// meaning of the fields depending on the variant. -/// -/// This type provides functions for determining whether the relocation -/// is scattered, and for accessing the fields of each variant. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Relocation { - pub r_word0: U32, - pub r_word1: U32, -} - -impl Relocation { - /// Determine whether this is a scattered relocation. - #[inline] - pub fn r_scattered(self, endian: E, cputype: u32) -> bool { - if cputype == CPU_TYPE_X86_64 { - false - } else { - self.r_word0.get(endian) & R_SCATTERED != 0 - } - } - - /// Return the fields of a plain relocation. - pub fn info(self, endian: E) -> RelocationInfo { - let r_address = self.r_word0.get(endian); - let r_word1 = self.r_word1.get(endian); - if endian.is_little_endian() { - RelocationInfo { - r_address, - r_symbolnum: r_word1 & 0x00ff_ffff, - r_pcrel: ((r_word1 >> 24) & 0x1) != 0, - r_length: ((r_word1 >> 25) & 0x3) as u8, - r_extern: ((r_word1 >> 27) & 0x1) != 0, - r_type: (r_word1 >> 28) as u8, - } - } else { - RelocationInfo { - r_address, - r_symbolnum: r_word1 >> 8, - r_pcrel: ((r_word1 >> 7) & 0x1) != 0, - r_length: ((r_word1 >> 5) & 0x3) as u8, - r_extern: ((r_word1 >> 4) & 0x1) != 0, - r_type: (r_word1 & 0xf) as u8, - } - } - } - - /// Return the fields of a scattered relocation. - pub fn scattered_info(self, endian: E) -> ScatteredRelocationInfo { - let r_word0 = self.r_word0.get(endian); - let r_value = self.r_word1.get(endian); - ScatteredRelocationInfo { - r_address: r_word0 & 0x00ff_ffff, - r_type: ((r_word0 >> 24) & 0xf) as u8, - r_length: ((r_word0 >> 28) & 0x3) as u8, - r_pcrel: ((r_word0 >> 30) & 0x1) != 0, - r_value, - } - } -} - -/* - * Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD - * format. The modifications from the original format were changing the value - * of the r_symbolnum field for "local" (r_extern == 0) relocation entries. - * This modification is required to support symbols in an arbitrary number of - * sections not just the three sections (text, data and bss) in a 4.3BSD file. - * Also the last 4 bits have had the r_type tag added to them. - */ - -#[derive(Debug, Clone, Copy)] -pub struct RelocationInfo { - /// offset in the section to what is being relocated - pub r_address: u32, - /// symbol index if r_extern == 1 or section ordinal if r_extern == 0 - pub r_symbolnum: u32, - /// was relocated pc relative already - pub r_pcrel: bool, - /// 0=byte, 1=word, 2=long, 3=quad - pub r_length: u8, - /// does not include value of sym referenced - pub r_extern: bool, - /// if not 0, machine specific relocation type - pub r_type: u8, -} - -impl RelocationInfo { - /// Combine the fields into a `Relocation`. - pub fn relocation(self, endian: E) -> Relocation { - let r_word0 = U32::new(endian, self.r_address); - let r_word1 = U32::new( - endian, - if endian.is_little_endian() { - self.r_symbolnum & 0x00ff_ffff - | u32::from(self.r_pcrel) << 24 - | u32::from(self.r_length & 0x3) << 25 - | u32::from(self.r_extern) << 27 - | u32::from(self.r_type) << 28 - } else { - self.r_symbolnum >> 8 - | u32::from(self.r_pcrel) << 7 - | u32::from(self.r_length & 0x3) << 5 - | u32::from(self.r_extern) << 4 - | u32::from(self.r_type) & 0xf - }, - ); - Relocation { r_word0, r_word1 } - } -} - -/// absolute relocation type for Mach-O files -pub const R_ABS: u8 = 0; - -/* - * The r_address is not really the address as it's name indicates but an offset. - * In 4.3BSD a.out objects this offset is from the start of the "segment" for - * which relocation entry is for (text or data). For Mach-O object files it is - * also an offset but from the start of the "section" for which the relocation - * entry is for. See comments in about the r_address feild - * in images for used with the dynamic linker. - * - * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal - * for the segment the symbol being relocated is in. These ordinals are the - * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these - * ordinals refer to the sections in the object file in the order their section - * structures appear in the headers of the object file they are in. The first - * section has the ordinal 1, the second 2, and so on. This means that the - * same ordinal in two different object files could refer to two different - * sections. And further could have still different ordinals when combined - * by the link-editor. The value R_ABS is used for relocation entries for - * absolute symbols which need no further relocation. - */ - -/* - * For RISC machines some of the references are split across two instructions - * and the instruction does not contain the complete value of the reference. - * In these cases a second, or paired relocation entry, follows each of these - * relocation entries, using a PAIR r_type, which contains the other part of the - * reference not contained in the instruction. This other part is stored in the - * pair's r_address field. The exact number of bits of the other part of the - * reference store in the r_address field is dependent on the particular - * relocation type for the particular architecture. - */ - -/* - * To make scattered loading by the link editor work correctly "local" - * relocation entries can't be used when the item to be relocated is the value - * of a symbol plus an offset (where the resulting expression is outside the - * block the link editor is moving, a blocks are divided at symbol addresses). - * In this case. where the item is a symbol value plus offset, the link editor - * needs to know more than just the section the symbol was defined. What is - * needed is the actual value of the symbol without the offset so it can do the - * relocation correctly based on where the value of the symbol got relocated to - * not the value of the expression (with the offset added to the symbol value). - * So for the NeXT 2.0 release no "local" relocation entries are ever used when - * there is a non-zero offset added to a symbol. The "external" and "local" - * relocation entries remain unchanged. - * - * The implementation is quite messy given the compatibility with the existing - * relocation entry format. The ASSUMPTION is that a section will never be - * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption - * allows the r_address (which is really an offset) to fit in 24 bits and high - * bit of the r_address field in the relocation_info structure to indicate - * it is really a scattered_relocation_info structure. Since these are only - * used in places where "local" relocation entries are used and not where - * "external" relocation entries are used the r_extern field has been removed. - * - * For scattered loading to work on a RISC machine where some of the references - * are split across two instructions the link editor needs to be assured that - * each reference has a unique 32 bit reference (that more than one reference is - * NOT sharing the same high 16 bits for example) so it move each referenced - * item independent of each other. Some compilers guarantees this but the - * compilers don't so scattered loading can be done on those that do guarantee - * this. - */ - -/// Bit set in `Relocation::r_word0` for scattered relocations. -pub const R_SCATTERED: u32 = 0x8000_0000; - -#[derive(Debug, Clone, Copy)] -pub struct ScatteredRelocationInfo { - /// offset in the section to what is being relocated - pub r_address: u32, - /// if not 0, machine specific relocation type - pub r_type: u8, - /// 0=byte, 1=word, 2=long, 3=quad - pub r_length: u8, - /// was relocated pc relative already - pub r_pcrel: bool, - /// the value the item to be relocated is referring to (without any offset added) - pub r_value: u32, -} - -impl ScatteredRelocationInfo { - /// Combine the fields into a `Relocation`. - pub fn relocation(self, endian: E) -> Relocation { - let r_word0 = U32::new( - endian, - self.r_address & 0x00ff_ffff - | u32::from(self.r_type & 0xf) << 24 - | u32::from(self.r_length & 0x3) << 28 - | u32::from(self.r_pcrel) << 30 - | R_SCATTERED, - ); - let r_word1 = U32::new(endian, self.r_value); - Relocation { r_word0, r_word1 } - } -} - -/* - * Relocation types used in a generic implementation. Relocation entries for - * normal things use the generic relocation as described above and their r_type - * is GENERIC_RELOC_VANILLA (a value of zero). - * - * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support - * the difference of two symbols defined in different sections. That is the - * expression "symbol1 - symbol2 + constant" is a relocatable expression when - * both symbols are defined in some section. For this type of relocation the - * both relocations entries are scattered relocation entries. The value of - * symbol1 is stored in the first relocation entry's r_value field and the - * value of symbol2 is stored in the pair's r_value field. - * - * A special case for a prebound lazy pointer is needed to beable to set the - * value of the lazy pointer back to its non-prebound state. This is done - * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation - * entry where the r_value feild is the value of the lazy pointer not prebound. - */ -/// generic relocation as described above -pub const GENERIC_RELOC_VANILLA: u8 = 0; -/// Only follows a GENERIC_RELOC_SECTDIFF -pub const GENERIC_RELOC_PAIR: u8 = 1; -pub const GENERIC_RELOC_SECTDIFF: u8 = 2; -/// prebound lazy pointer -pub const GENERIC_RELOC_PB_LA_PTR: u8 = 3; -pub const GENERIC_RELOC_LOCAL_SECTDIFF: u8 = 4; -/// thread local variables -pub const GENERIC_RELOC_TLV: u8 = 5; - -// Definitions from "/usr/include/mach-o/arm/reloc.h". - -/* - * Relocation types used in the arm implementation. Relocation entries for - * things other than instructions use the same generic relocation as described - * in and their r_type is ARM_RELOC_VANILLA, one of the - * *_SECTDIFF or the *_PB_LA_PTR types. The rest of the relocation types are - * for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be performed on. - */ -/// generic relocation as described above -pub const ARM_RELOC_VANILLA: u8 = 0; -/// the second relocation entry of a pair -pub const ARM_RELOC_PAIR: u8 = 1; -/// a PAIR follows with subtract symbol value -pub const ARM_RELOC_SECTDIFF: u8 = 2; -/// like ARM_RELOC_SECTDIFF, but the symbol referenced was local. -pub const ARM_RELOC_LOCAL_SECTDIFF: u8 = 3; -/// prebound lazy pointer -pub const ARM_RELOC_PB_LA_PTR: u8 = 4; -/// 24 bit branch displacement (to a word address) -pub const ARM_RELOC_BR24: u8 = 5; -/// 22 bit branch displacement (to a half-word address) -pub const ARM_THUMB_RELOC_BR22: u8 = 6; -/// obsolete - a thumb 32-bit branch instruction possibly needing page-spanning branch workaround -pub const ARM_THUMB_32BIT_BRANCH: u8 = 7; - -/* - * For these two r_type relocations they always have a pair following them - * and the r_length bits are used differently. The encoding of the - * r_length is as follows: - * low bit of r_length: - * 0 - :lower16: for movw instructions - * 1 - :upper16: for movt instructions - * high bit of r_length: - * 0 - arm instructions - * 1 - thumb instructions - * the other half of the relocated expression is in the following pair - * relocation entry in the the low 16 bits of r_address field. - */ -pub const ARM_RELOC_HALF: u8 = 8; -pub const ARM_RELOC_HALF_SECTDIFF: u8 = 9; - -// Definitions from "/usr/include/mach-o/arm64/reloc.h". - -/* - * Relocation types used in the arm64 implementation. - */ -/// for pointers -pub const ARM64_RELOC_UNSIGNED: u8 = 0; -/// must be followed by a ARM64_RELOC_UNSIGNED -pub const ARM64_RELOC_SUBTRACTOR: u8 = 1; -/// a B/BL instruction with 26-bit displacement -pub const ARM64_RELOC_BRANCH26: u8 = 2; -/// pc-rel distance to page of target -pub const ARM64_RELOC_PAGE21: u8 = 3; -/// offset within page, scaled by r_length -pub const ARM64_RELOC_PAGEOFF12: u8 = 4; -/// pc-rel distance to page of GOT slot -pub const ARM64_RELOC_GOT_LOAD_PAGE21: u8 = 5; -/// offset within page of GOT slot, scaled by r_length -pub const ARM64_RELOC_GOT_LOAD_PAGEOFF12: u8 = 6; -/// for pointers to GOT slots -pub const ARM64_RELOC_POINTER_TO_GOT: u8 = 7; -/// pc-rel distance to page of TLVP slot -pub const ARM64_RELOC_TLVP_LOAD_PAGE21: u8 = 8; -/// offset within page of TLVP slot, scaled by r_length -pub const ARM64_RELOC_TLVP_LOAD_PAGEOFF12: u8 = 9; -/// must be followed by PAGE21 or PAGEOFF12 -pub const ARM64_RELOC_ADDEND: u8 = 10; - -// An arm64e authenticated pointer. -// -// Represents a pointer to a symbol (like ARM64_RELOC_UNSIGNED). -// Additionally, the resulting pointer is signed. The signature is -// specified in the target location: the addend is restricted to the lower -// 32 bits (instead of the full 64 bits for ARM64_RELOC_UNSIGNED): -// -// |63|62|61-51|50-49| 48 |47 - 32|31 - 0| -// | 1| 0| 0 | key | addr | discriminator | addend | -// -// The key is one of: -// IA: 00 IB: 01 -// DA: 10 DB: 11 -// -// The discriminator field is used as extra signature diversification. -// -// The addr field indicates whether the target address should be blended -// into the discriminator. -// -pub const ARM64_RELOC_AUTHENTICATED_POINTER: u8 = 11; - -// Definitions from "/usr/include/mach-o/ppc/reloc.h". - -/* - * Relocation types used in the ppc implementation. Relocation entries for - * things other than instructions use the same generic relocation as described - * above and their r_type is RELOC_VANILLA. The rest of the relocation types - * are for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be performed on. - * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types - * except for PPC_RELOC_BR14. - * - * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was - * statically predicted setting or clearing the Y-bit based on the sign of the - * displacement or the opcode. If this is the case the static linker must flip - * the value of the Y-bit if the sign of the displacement changes for non-branch - * always conditions. - */ -/// generic relocation as described above -pub const PPC_RELOC_VANILLA: u8 = 0; -/// the second relocation entry of a pair -pub const PPC_RELOC_PAIR: u8 = 1; -/// 14 bit branch displacement (to a word address) -pub const PPC_RELOC_BR14: u8 = 2; -/// 24 bit branch displacement (to a word address) -pub const PPC_RELOC_BR24: u8 = 3; -/// a PAIR follows with the low half -pub const PPC_RELOC_HI16: u8 = 4; -/// a PAIR follows with the high half -pub const PPC_RELOC_LO16: u8 = 5; -/// Same as the RELOC_HI16 except the low 16 bits and the high 16 bits are added together -/// with the low 16 bits sign extended first. This means if bit 15 of the low 16 bits is -/// set the high 16 bits stored in the instruction will be adjusted. -pub const PPC_RELOC_HA16: u8 = 6; -/// Same as the LO16 except that the low 2 bits are not stored in the instruction and are -/// always zero. This is used in double word load/store instructions. -pub const PPC_RELOC_LO14: u8 = 7; -/// a PAIR follows with subtract symbol value -pub const PPC_RELOC_SECTDIFF: u8 = 8; -/// prebound lazy pointer -pub const PPC_RELOC_PB_LA_PTR: u8 = 9; -/// section difference forms of above. a PAIR -pub const PPC_RELOC_HI16_SECTDIFF: u8 = 10; -/// follows these with subtract symbol value -pub const PPC_RELOC_LO16_SECTDIFF: u8 = 11; -pub const PPC_RELOC_HA16_SECTDIFF: u8 = 12; -pub const PPC_RELOC_JBSR: u8 = 13; -pub const PPC_RELOC_LO14_SECTDIFF: u8 = 14; -/// like PPC_RELOC_SECTDIFF, but the symbol referenced was local. -pub const PPC_RELOC_LOCAL_SECTDIFF: u8 = 15; - -// Definitions from "/usr/include/mach-o/x86_64/reloc.h". - -/* - * Relocations for x86_64 are a bit different than for other architectures in - * Mach-O: Scattered relocations are not used. Almost all relocations produced - * by the compiler are external relocations. An external relocation has the - * r_extern bit set to 1 and the r_symbolnum field contains the symbol table - * index of the target label. - * - * When the assembler is generating relocations, if the target label is a local - * label (begins with 'L'), then the previous non-local label in the same - * section is used as the target of the external relocation. An addend is used - * with the distance from that non-local label to the target label. Only when - * there is no previous non-local label in the section is an internal - * relocation used. - * - * The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O does - * not have RELA relocations). For PC-relative relocations, the addend is - * stored directly in the instruction. This is different from other Mach-O - * architectures, which encode the addend minus the current section offset. - * - * The relocation types are: - * - * X86_64_RELOC_UNSIGNED // for absolute addresses - * X86_64_RELOC_SIGNED // for signed 32-bit displacement - * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement - * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry - * X86_64_RELOC_GOT // other GOT references - * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED - * - * The following are sample assembly instructions, followed by the relocation - * and section content they generate in an object file: - * - * call _foo - * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * E8 00 00 00 00 - * - * call _foo+4 - * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * E8 04 00 00 00 - * - * movq _foo@GOTPCREL(%rip), %rax - * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 48 8B 05 00 00 00 00 - * - * pushq _foo@GOTPCREL(%rip) - * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * FF 35 00 00 00 00 - * - * movl _foo(%rip), %eax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 8B 05 00 00 00 00 - * - * movl _foo+4(%rip), %eax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 8B 05 04 00 00 00 - * - * movb $0x12, _foo(%rip) - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * C6 05 FF FF FF FF 12 - * - * movl $0x12345678, _foo(%rip) - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * C7 05 FC FF FF FF 78 56 34 12 - * - * .quad _foo - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 00 00 00 00 - * - * .quad _foo+4 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 04 00 00 00 00 00 00 00 - * - * .quad _foo - _bar - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 00 00 00 00 - * - * .quad _foo - _bar + 4 - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 04 00 00 00 00 00 00 00 - * - * .long _foo - _bar - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 - * - * lea L1(%rip), %rax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev - * 48 8d 05 12 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * lea L0(%rip), %rax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 - * 48 8d 05 56 00 00 00 - * // assumes L0 is in third section and there is no previous non-local label. - * // The rip-relative-offset of 0x00000056 is L0-address_of_next_instruction. - * // address_of_next_instruction is the address of the relocation + 4. - * - * add $6,L0(%rip) - * r_type=X86_64_RELOC_SIGNED_1, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 - * 83 05 18 00 00 00 06 - * // assumes L0 is in third section and there is no previous non-local label. - * // The rip-relative-offset of 0x00000018 is L0-address_of_next_instruction. - * // address_of_next_instruction is the address of the relocation + 4 + 1. - * // The +1 comes from SIGNED_1. This is used because the relocation is not - * // at the end of the instruction. - * - * .quad L1 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * 12 00 00 00 00 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * .quad L0 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3 - * 56 00 00 00 00 00 00 00 - * // assumes L0 is in third section, has an address of 0x00000056 in .o - * // file, and there is no previous non-local label - * - * .quad _foo - . - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * EE FF FF FF FF FF FF FF - * // assumes _prev is the first non-local label 0x12 bytes before this - * // .quad - * - * .quad _foo - L1 - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * EE FF FF FF FF FF FF FF - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * .quad L1 - _prev - * // No relocations. This is an assembly time constant. - * 12 00 00 00 00 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * - * - * In final linked images, there are only two valid relocation kinds: - * - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index - * This tells dyld to add the address of a symbol to a pointer sized (8-byte) - * piece of data (i.e on disk the 8-byte piece of data contains the addend). The - * r_symbolnum contains the index into the symbol table of the target symbol. - * - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0 - * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount - * the containing image was loaded from its base address (e.g. slide). - * - */ -/// for absolute addresses -pub const X86_64_RELOC_UNSIGNED: u8 = 0; -/// for signed 32-bit displacement -pub const X86_64_RELOC_SIGNED: u8 = 1; -/// a CALL/JMP instruction with 32-bit displacement -pub const X86_64_RELOC_BRANCH: u8 = 2; -/// a MOVQ load of a GOT entry -pub const X86_64_RELOC_GOT_LOAD: u8 = 3; -/// other GOT references -pub const X86_64_RELOC_GOT: u8 = 4; -/// must be followed by a X86_64_RELOC_UNSIGNED -pub const X86_64_RELOC_SUBTRACTOR: u8 = 5; -/// for signed 32-bit displacement with a -1 addend -pub const X86_64_RELOC_SIGNED_1: u8 = 6; -/// for signed 32-bit displacement with a -2 addend -pub const X86_64_RELOC_SIGNED_2: u8 = 7; -/// for signed 32-bit displacement with a -4 addend -pub const X86_64_RELOC_SIGNED_4: u8 = 8; -/// for thread local variables -pub const X86_64_RELOC_TLV: u8 = 9; - -unsafe_impl_pod!(FatHeader, FatArch32, FatArch64,); -unsafe_impl_endian_pod!( - DyldCacheHeader, - DyldCacheMappingInfo, - DyldCacheImageInfo, - DyldSubCacheInfo, - MachHeader32, - MachHeader64, - LoadCommand, - LcStr, - SegmentCommand32, - SegmentCommand64, - Section32, - Section64, - Fvmlib, - FvmlibCommand, - Dylib, - DylibCommand, - SubFrameworkCommand, - SubClientCommand, - SubUmbrellaCommand, - SubLibraryCommand, - PreboundDylibCommand, - DylinkerCommand, - ThreadCommand, - RoutinesCommand32, - RoutinesCommand64, - SymtabCommand, - DysymtabCommand, - DylibTableOfContents, - DylibModule32, - DylibModule64, - DylibReference, - TwolevelHintsCommand, - TwolevelHint, - PrebindCksumCommand, - UuidCommand, - RpathCommand, - LinkeditDataCommand, - FilesetEntryCommand, - EncryptionInfoCommand32, - EncryptionInfoCommand64, - VersionMinCommand, - BuildVersionCommand, - BuildToolVersion, - DyldInfoCommand, - LinkerOptionCommand, - SymsegCommand, - IdentCommand, - FvmfileCommand, - EntryPointCommand, - SourceVersionCommand, - DataInCodeEntry, - //TlvDescriptor, - NoteCommand, - Nlist32, - Nlist64, - Relocation, -); diff --git a/vendor/object/src/pe.rs b/vendor/object/src/pe.rs deleted file mode 100644 index 64ccf06..0000000 --- a/vendor/object/src/pe.rs +++ /dev/null @@ -1,3056 +0,0 @@ -//! PE/COFF definitions. -//! -//! These definitions are independent of read/write support, although we do implement -//! some traits useful for those. -//! -//! This module is based heavily on "winnt.h" (10.0.17763.0). - -#![allow(missing_docs)] - -use core::convert::TryInto; - -use crate::endian::{I32Bytes, LittleEndian as LE, U16Bytes, U32Bytes, I32, U16, U32, U64}; -use crate::pod::Pod; - -/// MZ -pub const IMAGE_DOS_SIGNATURE: u16 = 0x5A4D; -/// NE -pub const IMAGE_OS2_SIGNATURE: u16 = 0x454E; -/// LE -pub const IMAGE_OS2_SIGNATURE_LE: u16 = 0x454C; -/// LE -pub const IMAGE_VXD_SIGNATURE: u16 = 0x454C; -/// PE00 -pub const IMAGE_NT_SIGNATURE: u32 = 0x0000_4550; - -/// DOS .EXE header -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDosHeader { - /// Magic number - pub e_magic: U16, - /// Bytes on last page of file - pub e_cblp: U16, - /// Pages in file - pub e_cp: U16, - /// Relocations - pub e_crlc: U16, - /// Size of header in paragraphs - pub e_cparhdr: U16, - /// Minimum extra paragraphs needed - pub e_minalloc: U16, - /// Maximum extra paragraphs needed - pub e_maxalloc: U16, - /// Initial (relative) SS value - pub e_ss: U16, - /// Initial SP value - pub e_sp: U16, - /// Checksum - pub e_csum: U16, - /// Initial IP value - pub e_ip: U16, - /// Initial (relative) CS value - pub e_cs: U16, - /// File address of relocation table - pub e_lfarlc: U16, - /// Overlay number - pub e_ovno: U16, - /// Reserved words - pub e_res: [U16; 4], - /// OEM identifier (for e_oeminfo) - pub e_oemid: U16, - /// OEM information; e_oemid specific - pub e_oeminfo: U16, - /// Reserved words - pub e_res2: [U16; 10], - /// File address of new exe header - pub e_lfanew: U32, -} - -/// OS/2 .EXE header -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageOs2Header { - /// Magic number - pub ne_magic: U16, - /// Version number - pub ne_ver: i8, - /// Revision number - pub ne_rev: i8, - /// Offset of Entry Table - pub ne_enttab: U16, - /// Number of bytes in Entry Table - pub ne_cbenttab: U16, - /// Checksum of whole file - pub ne_crc: I32, - /// Flag word - pub ne_flags: U16, - /// Automatic data segment number - pub ne_autodata: U16, - /// Initial heap allocation - pub ne_heap: U16, - /// Initial stack allocation - pub ne_stack: U16, - /// Initial CS:IP setting - pub ne_csip: I32, - /// Initial SS:SP setting - pub ne_sssp: I32, - /// Count of file segments - pub ne_cseg: U16, - /// Entries in Module Reference Table - pub ne_cmod: U16, - /// Size of non-resident name table - pub ne_cbnrestab: U16, - /// Offset of Segment Table - pub ne_segtab: U16, - /// Offset of Resource Table - pub ne_rsrctab: U16, - /// Offset of resident name table - pub ne_restab: U16, - /// Offset of Module Reference Table - pub ne_modtab: U16, - /// Offset of Imported Names Table - pub ne_imptab: U16, - /// Offset of Non-resident Names Table - pub ne_nrestab: I32, - /// Count of movable entries - pub ne_cmovent: U16, - /// Segment alignment shift count - pub ne_align: U16, - /// Count of resource segments - pub ne_cres: U16, - /// Target Operating system - pub ne_exetyp: u8, - /// Other .EXE flags - pub ne_flagsothers: u8, - /// offset to return thunks - pub ne_pretthunks: U16, - /// offset to segment ref. bytes - pub ne_psegrefbytes: U16, - /// Minimum code swap area size - pub ne_swaparea: U16, - /// Expected Windows version number - pub ne_expver: U16, -} - -/// Windows VXD header -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageVxdHeader { - /// Magic number - pub e32_magic: U16, - /// The byte ordering for the VXD - pub e32_border: u8, - /// The word ordering for the VXD - pub e32_worder: u8, - /// The EXE format level for now = 0 - pub e32_level: U32, - /// The CPU type - pub e32_cpu: U16, - /// The OS type - pub e32_os: U16, - /// Module version - pub e32_ver: U32, - /// Module flags - pub e32_mflags: U32, - /// Module # pages - pub e32_mpages: U32, - /// Object # for instruction pointer - pub e32_startobj: U32, - /// Extended instruction pointer - pub e32_eip: U32, - /// Object # for stack pointer - pub e32_stackobj: U32, - /// Extended stack pointer - pub e32_esp: U32, - /// VXD page size - pub e32_pagesize: U32, - /// Last page size in VXD - pub e32_lastpagesize: U32, - /// Fixup section size - pub e32_fixupsize: U32, - /// Fixup section checksum - pub e32_fixupsum: U32, - /// Loader section size - pub e32_ldrsize: U32, - /// Loader section checksum - pub e32_ldrsum: U32, - /// Object table offset - pub e32_objtab: U32, - /// Number of objects in module - pub e32_objcnt: U32, - /// Object page map offset - pub e32_objmap: U32, - /// Object iterated data map offset - pub e32_itermap: U32, - /// Offset of Resource Table - pub e32_rsrctab: U32, - /// Number of resource entries - pub e32_rsrccnt: U32, - /// Offset of resident name table - pub e32_restab: U32, - /// Offset of Entry Table - pub e32_enttab: U32, - /// Offset of Module Directive Table - pub e32_dirtab: U32, - /// Number of module directives - pub e32_dircnt: U32, - /// Offset of Fixup Page Table - pub e32_fpagetab: U32, - /// Offset of Fixup Record Table - pub e32_frectab: U32, - /// Offset of Import Module Name Table - pub e32_impmod: U32, - /// Number of entries in Import Module Name Table - pub e32_impmodcnt: U32, - /// Offset of Import Procedure Name Table - pub e32_impproc: U32, - /// Offset of Per-Page Checksum Table - pub e32_pagesum: U32, - /// Offset of Enumerated Data Pages - pub e32_datapage: U32, - /// Number of preload pages - pub e32_preload: U32, - /// Offset of Non-resident Names Table - pub e32_nrestab: U32, - /// Size of Non-resident Name Table - pub e32_cbnrestab: U32, - /// Non-resident Name Table Checksum - pub e32_nressum: U32, - /// Object # for automatic data object - pub e32_autodata: U32, - /// Offset of the debugging information - pub e32_debuginfo: U32, - /// The length of the debugging info. in bytes - pub e32_debuglen: U32, - /// Number of instance pages in preload section of VXD file - pub e32_instpreload: U32, - /// Number of instance pages in demand load section of VXD file - pub e32_instdemand: U32, - /// Size of heap - for 16-bit apps - pub e32_heapsize: U32, - /// Reserved words - pub e32_res3: [u8; 12], - pub e32_winresoff: U32, - pub e32_winreslen: U32, - /// Device ID for VxD - pub e32_devid: U16, - /// DDK version for VxD - pub e32_ddkver: U16, -} - -/// A PE rich header entry. -/// -/// Rich headers have no official documentation, but have been heavily -/// reversed-engineered and documented in the wild, e.g.: -/// * `http://www.ntcore.com/files/richsign.htm` -/// * `https://www.researchgate.net/figure/Structure-of-the-Rich-Header_fig1_318145388` -/// -/// This data is "masked", i.e. XORed with a checksum derived from the file data. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct MaskedRichHeaderEntry { - pub masked_comp_id: U32, - pub masked_count: U32, -} - -// -// File header format. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageFileHeader { - pub machine: U16, - pub number_of_sections: U16, - pub time_date_stamp: U32, - pub pointer_to_symbol_table: U32, - pub number_of_symbols: U32, - pub size_of_optional_header: U16, - pub characteristics: U16, -} - -pub const IMAGE_SIZEOF_FILE_HEADER: usize = 20; - -/// Relocation info stripped from file. -pub const IMAGE_FILE_RELOCS_STRIPPED: u16 = 0x0001; -/// File is executable (i.e. no unresolved external references). -pub const IMAGE_FILE_EXECUTABLE_IMAGE: u16 = 0x0002; -/// Line numbers stripped from file. -pub const IMAGE_FILE_LINE_NUMS_STRIPPED: u16 = 0x0004; -/// Local symbols stripped from file. -pub const IMAGE_FILE_LOCAL_SYMS_STRIPPED: u16 = 0x0008; -/// Aggressively trim working set -pub const IMAGE_FILE_AGGRESIVE_WS_TRIM: u16 = 0x0010; -/// App can handle >2gb addresses -pub const IMAGE_FILE_LARGE_ADDRESS_AWARE: u16 = 0x0020; -/// Bytes of machine word are reversed. -pub const IMAGE_FILE_BYTES_REVERSED_LO: u16 = 0x0080; -/// 32 bit word machine. -pub const IMAGE_FILE_32BIT_MACHINE: u16 = 0x0100; -/// Debugging info stripped from file in .DBG file -pub const IMAGE_FILE_DEBUG_STRIPPED: u16 = 0x0200; -/// If Image is on removable media, copy and run from the swap file. -pub const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP: u16 = 0x0400; -/// If Image is on Net, copy and run from the swap file. -pub const IMAGE_FILE_NET_RUN_FROM_SWAP: u16 = 0x0800; -/// System File. -pub const IMAGE_FILE_SYSTEM: u16 = 0x1000; -/// File is a DLL. -pub const IMAGE_FILE_DLL: u16 = 0x2000; -/// File should only be run on a UP machine -pub const IMAGE_FILE_UP_SYSTEM_ONLY: u16 = 0x4000; -/// Bytes of machine word are reversed. -pub const IMAGE_FILE_BYTES_REVERSED_HI: u16 = 0x8000; - -pub const IMAGE_FILE_MACHINE_UNKNOWN: u16 = 0; -/// Useful for indicating we want to interact with the host and not a WoW guest. -pub const IMAGE_FILE_MACHINE_TARGET_HOST: u16 = 0x0001; -/// Intel 386. -pub const IMAGE_FILE_MACHINE_I386: u16 = 0x014c; -/// MIPS little-endian, 0x160 big-endian -pub const IMAGE_FILE_MACHINE_R3000: u16 = 0x0162; -/// MIPS little-endian -pub const IMAGE_FILE_MACHINE_R4000: u16 = 0x0166; -/// MIPS little-endian -pub const IMAGE_FILE_MACHINE_R10000: u16 = 0x0168; -/// MIPS little-endian WCE v2 -pub const IMAGE_FILE_MACHINE_WCEMIPSV2: u16 = 0x0169; -/// Alpha_AXP -pub const IMAGE_FILE_MACHINE_ALPHA: u16 = 0x0184; -/// SH3 little-endian -pub const IMAGE_FILE_MACHINE_SH3: u16 = 0x01a2; -pub const IMAGE_FILE_MACHINE_SH3DSP: u16 = 0x01a3; -/// SH3E little-endian -pub const IMAGE_FILE_MACHINE_SH3E: u16 = 0x01a4; -/// SH4 little-endian -pub const IMAGE_FILE_MACHINE_SH4: u16 = 0x01a6; -/// SH5 -pub const IMAGE_FILE_MACHINE_SH5: u16 = 0x01a8; -/// ARM Little-Endian -pub const IMAGE_FILE_MACHINE_ARM: u16 = 0x01c0; -/// ARM Thumb/Thumb-2 Little-Endian -pub const IMAGE_FILE_MACHINE_THUMB: u16 = 0x01c2; -/// ARM Thumb-2 Little-Endian -pub const IMAGE_FILE_MACHINE_ARMNT: u16 = 0x01c4; -pub const IMAGE_FILE_MACHINE_AM33: u16 = 0x01d3; -/// IBM PowerPC Little-Endian -pub const IMAGE_FILE_MACHINE_POWERPC: u16 = 0x01F0; -pub const IMAGE_FILE_MACHINE_POWERPCFP: u16 = 0x01f1; -/// Intel 64 -pub const IMAGE_FILE_MACHINE_IA64: u16 = 0x0200; -/// MIPS -pub const IMAGE_FILE_MACHINE_MIPS16: u16 = 0x0266; -/// ALPHA64 -pub const IMAGE_FILE_MACHINE_ALPHA64: u16 = 0x0284; -/// MIPS -pub const IMAGE_FILE_MACHINE_MIPSFPU: u16 = 0x0366; -/// MIPS -pub const IMAGE_FILE_MACHINE_MIPSFPU16: u16 = 0x0466; -pub const IMAGE_FILE_MACHINE_AXP64: u16 = IMAGE_FILE_MACHINE_ALPHA64; -/// Infineon -pub const IMAGE_FILE_MACHINE_TRICORE: u16 = 0x0520; -pub const IMAGE_FILE_MACHINE_CEF: u16 = 0x0CEF; -/// EFI Byte Code -pub const IMAGE_FILE_MACHINE_EBC: u16 = 0x0EBC; -/// AMD64 (K8) -pub const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664; -/// M32R little-endian -pub const IMAGE_FILE_MACHINE_M32R: u16 = 0x9041; -/// ARM64 Little-Endian -pub const IMAGE_FILE_MACHINE_ARM64: u16 = 0xAA64; -/// ARM64EC ("Emulation Compatible") -pub const IMAGE_FILE_MACHINE_ARM64EC: u16 = 0xA641; -pub const IMAGE_FILE_MACHINE_CEE: u16 = 0xC0EE; -/// RISCV32 -pub const IMAGE_FILE_MACHINE_RISCV32: u16 = 0x5032; -/// RISCV64 -pub const IMAGE_FILE_MACHINE_RISCV64: u16 = 0x5064; -/// RISCV128 -pub const IMAGE_FILE_MACHINE_RISCV128: u16 = 0x5128; - -// -// Directory format. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDataDirectory { - pub virtual_address: U32, - pub size: U32, -} - -pub const IMAGE_NUMBEROF_DIRECTORY_ENTRIES: usize = 16; - -// -// Optional header format. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageOptionalHeader32 { - // Standard fields. - pub magic: U16, - pub major_linker_version: u8, - pub minor_linker_version: u8, - pub size_of_code: U32, - pub size_of_initialized_data: U32, - pub size_of_uninitialized_data: U32, - pub address_of_entry_point: U32, - pub base_of_code: U32, - pub base_of_data: U32, - - // NT additional fields. - pub image_base: U32, - pub section_alignment: U32, - pub file_alignment: U32, - pub major_operating_system_version: U16, - pub minor_operating_system_version: U16, - pub major_image_version: U16, - pub minor_image_version: U16, - pub major_subsystem_version: U16, - pub minor_subsystem_version: U16, - pub win32_version_value: U32, - pub size_of_image: U32, - pub size_of_headers: U32, - pub check_sum: U32, - pub subsystem: U16, - pub dll_characteristics: U16, - pub size_of_stack_reserve: U32, - pub size_of_stack_commit: U32, - pub size_of_heap_reserve: U32, - pub size_of_heap_commit: U32, - pub loader_flags: U32, - pub number_of_rva_and_sizes: U32, - //pub data_directory: [ImageDataDirectory; IMAGE_NUMBEROF_DIRECTORY_ENTRIES], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageRomOptionalHeader { - pub magic: U16, - pub major_linker_version: u8, - pub minor_linker_version: u8, - pub size_of_code: U32, - pub size_of_initialized_data: U32, - pub size_of_uninitialized_data: U32, - pub address_of_entry_point: U32, - pub base_of_code: U32, - pub base_of_data: U32, - pub base_of_bss: U32, - pub gpr_mask: U32, - pub cpr_mask: [U32; 4], - pub gp_value: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageOptionalHeader64 { - pub magic: U16, - pub major_linker_version: u8, - pub minor_linker_version: u8, - pub size_of_code: U32, - pub size_of_initialized_data: U32, - pub size_of_uninitialized_data: U32, - pub address_of_entry_point: U32, - pub base_of_code: U32, - pub image_base: U64, - pub section_alignment: U32, - pub file_alignment: U32, - pub major_operating_system_version: U16, - pub minor_operating_system_version: U16, - pub major_image_version: U16, - pub minor_image_version: U16, - pub major_subsystem_version: U16, - pub minor_subsystem_version: U16, - pub win32_version_value: U32, - pub size_of_image: U32, - pub size_of_headers: U32, - pub check_sum: U32, - pub subsystem: U16, - pub dll_characteristics: U16, - pub size_of_stack_reserve: U64, - pub size_of_stack_commit: U64, - pub size_of_heap_reserve: U64, - pub size_of_heap_commit: U64, - pub loader_flags: U32, - pub number_of_rva_and_sizes: U32, - //pub data_directory: [ImageDataDirectory; IMAGE_NUMBEROF_DIRECTORY_ENTRIES], -} - -pub const IMAGE_NT_OPTIONAL_HDR32_MAGIC: u16 = 0x10b; -pub const IMAGE_NT_OPTIONAL_HDR64_MAGIC: u16 = 0x20b; -pub const IMAGE_ROM_OPTIONAL_HDR_MAGIC: u16 = 0x107; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageNtHeaders64 { - pub signature: U32, - pub file_header: ImageFileHeader, - pub optional_header: ImageOptionalHeader64, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageNtHeaders32 { - pub signature: U32, - pub file_header: ImageFileHeader, - pub optional_header: ImageOptionalHeader32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageRomHeaders { - pub file_header: ImageFileHeader, - pub optional_header: ImageRomOptionalHeader, -} - -// Values for `ImageOptionalHeader*::subsystem`. - -/// Unknown subsystem. -pub const IMAGE_SUBSYSTEM_UNKNOWN: u16 = 0; -/// Image doesn't require a subsystem. -pub const IMAGE_SUBSYSTEM_NATIVE: u16 = 1; -/// Image runs in the Windows GUI subsystem. -pub const IMAGE_SUBSYSTEM_WINDOWS_GUI: u16 = 2; -/// Image runs in the Windows character subsystem. -pub const IMAGE_SUBSYSTEM_WINDOWS_CUI: u16 = 3; -/// image runs in the OS/2 character subsystem. -pub const IMAGE_SUBSYSTEM_OS2_CUI: u16 = 5; -/// image runs in the Posix character subsystem. -pub const IMAGE_SUBSYSTEM_POSIX_CUI: u16 = 7; -/// image is a native Win9x driver. -pub const IMAGE_SUBSYSTEM_NATIVE_WINDOWS: u16 = 8; -/// Image runs in the Windows CE subsystem. -pub const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: u16 = 9; -pub const IMAGE_SUBSYSTEM_EFI_APPLICATION: u16 = 10; -pub const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: u16 = 11; -pub const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: u16 = 12; -pub const IMAGE_SUBSYSTEM_EFI_ROM: u16 = 13; -pub const IMAGE_SUBSYSTEM_XBOX: u16 = 14; -pub const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: u16 = 16; -pub const IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG: u16 = 17; - -// Values for `ImageOptionalHeader*::dll_characteristics`. - -// IMAGE_LIBRARY_PROCESS_INIT 0x0001 // Reserved. -// IMAGE_LIBRARY_PROCESS_TERM 0x0002 // Reserved. -// IMAGE_LIBRARY_THREAD_INIT 0x0004 // Reserved. -// IMAGE_LIBRARY_THREAD_TERM 0x0008 // Reserved. -/// Image can handle a high entropy 64-bit virtual address space. -pub const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA: u16 = 0x0020; -/// DLL can move. -pub const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE: u16 = 0x0040; -/// Code Integrity Image -pub const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY: u16 = 0x0080; -/// Image is NX compatible -pub const IMAGE_DLLCHARACTERISTICS_NX_COMPAT: u16 = 0x0100; -/// Image understands isolation and doesn't want it -pub const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION: u16 = 0x0200; -/// Image does not use SEH. No SE handler may reside in this image -pub const IMAGE_DLLCHARACTERISTICS_NO_SEH: u16 = 0x0400; -/// Do not bind this image. -pub const IMAGE_DLLCHARACTERISTICS_NO_BIND: u16 = 0x0800; -/// Image should execute in an AppContainer -pub const IMAGE_DLLCHARACTERISTICS_APPCONTAINER: u16 = 0x1000; -/// Driver uses WDM model -pub const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER: u16 = 0x2000; -/// Image supports Control Flow Guard. -pub const IMAGE_DLLCHARACTERISTICS_GUARD_CF: u16 = 0x4000; -pub const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE: u16 = 0x8000; - -// Indices for `ImageOptionalHeader*::data_directory`. - -/// Export Directory -pub const IMAGE_DIRECTORY_ENTRY_EXPORT: usize = 0; -/// Import Directory -pub const IMAGE_DIRECTORY_ENTRY_IMPORT: usize = 1; -/// Resource Directory -pub const IMAGE_DIRECTORY_ENTRY_RESOURCE: usize = 2; -/// Exception Directory -pub const IMAGE_DIRECTORY_ENTRY_EXCEPTION: usize = 3; -/// Security Directory -pub const IMAGE_DIRECTORY_ENTRY_SECURITY: usize = 4; -/// Base Relocation Table -pub const IMAGE_DIRECTORY_ENTRY_BASERELOC: usize = 5; -/// Debug Directory -pub const IMAGE_DIRECTORY_ENTRY_DEBUG: usize = 6; -// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) -/// Architecture Specific Data -pub const IMAGE_DIRECTORY_ENTRY_ARCHITECTURE: usize = 7; -/// RVA of GP -pub const IMAGE_DIRECTORY_ENTRY_GLOBALPTR: usize = 8; -/// TLS Directory -pub const IMAGE_DIRECTORY_ENTRY_TLS: usize = 9; -/// Load Configuration Directory -pub const IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG: usize = 10; -/// Bound Import Directory in headers -pub const IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT: usize = 11; -/// Import Address Table -pub const IMAGE_DIRECTORY_ENTRY_IAT: usize = 12; -/// Delay Load Import Descriptors -pub const IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT: usize = 13; -/// COM Runtime descriptor -pub const IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: usize = 14; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(C)] -pub struct Guid(pub [u8; 16]); - -impl Guid { - #[inline] - pub fn data1(self) -> U32 { - U32::from_bytes(self.0[0..4].try_into().unwrap()) - } - - #[inline] - pub fn data2(self) -> U16 { - U16::from_bytes(self.0[4..6].try_into().unwrap()) - } - - #[inline] - pub fn data3(self) -> U16 { - U16::from_bytes(self.0[6..8].try_into().unwrap()) - } - - #[inline] - pub fn data4(self) -> [u8; 8] { - self.0[8..16].try_into().unwrap() - } -} - -pub use Guid as ClsId; - -/// Non-COFF Object file header -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AnonObjectHeader { - /// Must be IMAGE_FILE_MACHINE_UNKNOWN - pub sig1: U16, - /// Must be 0xffff - pub sig2: U16, - /// >= 1 (implies the ClsId field is present) - pub version: U16, - pub machine: U16, - pub time_date_stamp: U32, - /// Used to invoke CoCreateInstance - pub class_id: ClsId, - /// Size of data that follows the header - pub size_of_data: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AnonObjectHeaderV2 { - /// Must be IMAGE_FILE_MACHINE_UNKNOWN - pub sig1: U16, - /// Must be 0xffff - pub sig2: U16, - /// >= 2 (implies the Flags field is present - otherwise V1) - pub version: U16, - pub machine: U16, - pub time_date_stamp: U32, - /// Used to invoke CoCreateInstance - pub class_id: ClsId, - /// Size of data that follows the header - pub size_of_data: U32, - /// 0x1 -> contains metadata - pub flags: U32, - /// Size of CLR metadata - pub meta_data_size: U32, - /// Offset of CLR metadata - pub meta_data_offset: U32, -} - -/// The required value of `AnonObjectHeaderBigobj::class_id`. -pub const ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID: ClsId = ClsId([ - 0xC7, 0xA1, 0xBA, 0xD1, 0xEE, 0xBA, 0xA9, 0x4B, 0xAF, 0x20, 0xFA, 0xF6, 0x6A, 0xA4, 0xDC, 0xB8, -]); - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AnonObjectHeaderBigobj { - /* same as ANON_OBJECT_HEADER_V2 */ - /// Must be IMAGE_FILE_MACHINE_UNKNOWN - pub sig1: U16, - /// Must be 0xffff - pub sig2: U16, - /// >= 2 (implies the Flags field is present) - pub version: U16, - /// Actual machine - IMAGE_FILE_MACHINE_xxx - pub machine: U16, - pub time_date_stamp: U32, - /// Must be `ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID`. - pub class_id: ClsId, - /// Size of data that follows the header - pub size_of_data: U32, - /// 0x1 -> contains metadata - pub flags: U32, - /// Size of CLR metadata - pub meta_data_size: U32, - /// Offset of CLR metadata - pub meta_data_offset: U32, - - /* bigobj specifics */ - /// extended from WORD - pub number_of_sections: U32, - pub pointer_to_symbol_table: U32, - pub number_of_symbols: U32, -} - -pub const IMAGE_SIZEOF_SHORT_NAME: usize = 8; - -// -// Section header format. -// - -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct ImageSectionHeader { - pub name: [u8; IMAGE_SIZEOF_SHORT_NAME], - pub virtual_size: U32, - pub virtual_address: U32, - pub size_of_raw_data: U32, - pub pointer_to_raw_data: U32, - pub pointer_to_relocations: U32, - pub pointer_to_linenumbers: U32, - pub number_of_relocations: U16, - pub number_of_linenumbers: U16, - pub characteristics: U32, -} - -pub const IMAGE_SIZEOF_SECTION_HEADER: usize = 40; - -// Values for `ImageSectionHeader::characteristics`. - -// IMAGE_SCN_TYPE_REG 0x00000000 // Reserved. -// IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved. -// IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved. -// IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved. -/// Reserved. -pub const IMAGE_SCN_TYPE_NO_PAD: u32 = 0x0000_0008; -// IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved. - -/// Section contains code. -pub const IMAGE_SCN_CNT_CODE: u32 = 0x0000_0020; -/// Section contains initialized data. -pub const IMAGE_SCN_CNT_INITIALIZED_DATA: u32 = 0x0000_0040; -/// Section contains uninitialized data. -pub const IMAGE_SCN_CNT_UNINITIALIZED_DATA: u32 = 0x0000_0080; - -/// Reserved. -pub const IMAGE_SCN_LNK_OTHER: u32 = 0x0000_0100; -/// Section contains comments or some other type of information. -pub const IMAGE_SCN_LNK_INFO: u32 = 0x0000_0200; -// IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved. -/// Section contents will not become part of image. -pub const IMAGE_SCN_LNK_REMOVE: u32 = 0x0000_0800; -/// Section contents comdat. -pub const IMAGE_SCN_LNK_COMDAT: u32 = 0x0000_1000; -// 0x00002000 // Reserved. -// IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000 -/// Reset speculative exceptions handling bits in the TLB entries for this section. -pub const IMAGE_SCN_NO_DEFER_SPEC_EXC: u32 = 0x0000_4000; -/// Section content can be accessed relative to GP -pub const IMAGE_SCN_GPREL: u32 = 0x0000_8000; -pub const IMAGE_SCN_MEM_FARDATA: u32 = 0x0000_8000; -// IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000 -pub const IMAGE_SCN_MEM_PURGEABLE: u32 = 0x0002_0000; -pub const IMAGE_SCN_MEM_16BIT: u32 = 0x0002_0000; -pub const IMAGE_SCN_MEM_LOCKED: u32 = 0x0004_0000; -pub const IMAGE_SCN_MEM_PRELOAD: u32 = 0x0008_0000; - -pub const IMAGE_SCN_ALIGN_1BYTES: u32 = 0x0010_0000; -pub const IMAGE_SCN_ALIGN_2BYTES: u32 = 0x0020_0000; -pub const IMAGE_SCN_ALIGN_4BYTES: u32 = 0x0030_0000; -pub const IMAGE_SCN_ALIGN_8BYTES: u32 = 0x0040_0000; -/// Default alignment if no others are specified. -pub const IMAGE_SCN_ALIGN_16BYTES: u32 = 0x0050_0000; -pub const IMAGE_SCN_ALIGN_32BYTES: u32 = 0x0060_0000; -pub const IMAGE_SCN_ALIGN_64BYTES: u32 = 0x0070_0000; -pub const IMAGE_SCN_ALIGN_128BYTES: u32 = 0x0080_0000; -pub const IMAGE_SCN_ALIGN_256BYTES: u32 = 0x0090_0000; -pub const IMAGE_SCN_ALIGN_512BYTES: u32 = 0x00A0_0000; -pub const IMAGE_SCN_ALIGN_1024BYTES: u32 = 0x00B0_0000; -pub const IMAGE_SCN_ALIGN_2048BYTES: u32 = 0x00C0_0000; -pub const IMAGE_SCN_ALIGN_4096BYTES: u32 = 0x00D0_0000; -pub const IMAGE_SCN_ALIGN_8192BYTES: u32 = 0x00E0_0000; -// Unused 0x00F0_0000 -pub const IMAGE_SCN_ALIGN_MASK: u32 = 0x00F0_0000; - -/// Section contains extended relocations. -pub const IMAGE_SCN_LNK_NRELOC_OVFL: u32 = 0x0100_0000; -/// Section can be discarded. -pub const IMAGE_SCN_MEM_DISCARDABLE: u32 = 0x0200_0000; -/// Section is not cacheable. -pub const IMAGE_SCN_MEM_NOT_CACHED: u32 = 0x0400_0000; -/// Section is not pageable. -pub const IMAGE_SCN_MEM_NOT_PAGED: u32 = 0x0800_0000; -/// Section is shareable. -pub const IMAGE_SCN_MEM_SHARED: u32 = 0x1000_0000; -/// Section is executable. -pub const IMAGE_SCN_MEM_EXECUTE: u32 = 0x2000_0000; -/// Section is readable. -pub const IMAGE_SCN_MEM_READ: u32 = 0x4000_0000; -/// Section is writeable. -pub const IMAGE_SCN_MEM_WRITE: u32 = 0x8000_0000; - -// -// TLS Characteristic Flags -// -/// Tls index is scaled -pub const IMAGE_SCN_SCALE_INDEX: u32 = 0x0000_0001; - -// -// Symbol format. -// - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSymbol { - /// If first 4 bytes are 0, then second 4 bytes are offset into string table. - pub name: [u8; 8], - pub value: U32Bytes, - pub section_number: U16Bytes, - pub typ: U16Bytes, - pub storage_class: u8, - pub number_of_aux_symbols: u8, -} - -pub const IMAGE_SIZEOF_SYMBOL: usize = 18; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSymbolBytes(pub [u8; IMAGE_SIZEOF_SYMBOL]); - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSymbolEx { - /// If first 4 bytes are 0, then second 4 bytes are offset into string table. - pub name: [u8; 8], - pub value: U32Bytes, - pub section_number: I32Bytes, - pub typ: U16Bytes, - pub storage_class: u8, - pub number_of_aux_symbols: u8, -} - -pub const IMAGE_SIZEOF_SYMBOL_EX: usize = 20; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSymbolExBytes(pub [u8; IMAGE_SIZEOF_SYMBOL_EX]); - -// Values for `ImageSymbol::section_number`. -// -// Symbols have a section number of the section in which they are -// defined. Otherwise, section numbers have the following meanings: - -/// Symbol is undefined or is common. -pub const IMAGE_SYM_UNDEFINED: i32 = 0; -/// Symbol is an absolute value. -pub const IMAGE_SYM_ABSOLUTE: i32 = -1; -/// Symbol is a special debug item. -pub const IMAGE_SYM_DEBUG: i32 = -2; -/// Values 0xFF00-0xFFFF are special -pub const IMAGE_SYM_SECTION_MAX: u16 = 0xFEFF; -pub const IMAGE_SYM_SECTION_MAX_EX: u32 = 0x7fff_ffff; - -// Values for `ImageSymbol::typ` (basic component). - -/// no type. -pub const IMAGE_SYM_TYPE_NULL: u16 = 0x0000; -pub const IMAGE_SYM_TYPE_VOID: u16 = 0x0001; -/// type character. -pub const IMAGE_SYM_TYPE_CHAR: u16 = 0x0002; -/// type short integer. -pub const IMAGE_SYM_TYPE_SHORT: u16 = 0x0003; -pub const IMAGE_SYM_TYPE_INT: u16 = 0x0004; -pub const IMAGE_SYM_TYPE_LONG: u16 = 0x0005; -pub const IMAGE_SYM_TYPE_FLOAT: u16 = 0x0006; -pub const IMAGE_SYM_TYPE_DOUBLE: u16 = 0x0007; -pub const IMAGE_SYM_TYPE_STRUCT: u16 = 0x0008; -pub const IMAGE_SYM_TYPE_UNION: u16 = 0x0009; -/// enumeration. -pub const IMAGE_SYM_TYPE_ENUM: u16 = 0x000A; -/// member of enumeration. -pub const IMAGE_SYM_TYPE_MOE: u16 = 0x000B; -pub const IMAGE_SYM_TYPE_BYTE: u16 = 0x000C; -pub const IMAGE_SYM_TYPE_WORD: u16 = 0x000D; -pub const IMAGE_SYM_TYPE_UINT: u16 = 0x000E; -pub const IMAGE_SYM_TYPE_DWORD: u16 = 0x000F; -pub const IMAGE_SYM_TYPE_PCODE: u16 = 0x8000; - -// Values for `ImageSymbol::typ` (derived component). - -/// no derived type. -pub const IMAGE_SYM_DTYPE_NULL: u16 = 0; -/// pointer. -pub const IMAGE_SYM_DTYPE_POINTER: u16 = 1; -/// function. -pub const IMAGE_SYM_DTYPE_FUNCTION: u16 = 2; -/// array. -pub const IMAGE_SYM_DTYPE_ARRAY: u16 = 3; - -// Values for `ImageSymbol::storage_class`. -pub const IMAGE_SYM_CLASS_END_OF_FUNCTION: u8 = 0xff; -pub const IMAGE_SYM_CLASS_NULL: u8 = 0x00; -pub const IMAGE_SYM_CLASS_AUTOMATIC: u8 = 0x01; -pub const IMAGE_SYM_CLASS_EXTERNAL: u8 = 0x02; -pub const IMAGE_SYM_CLASS_STATIC: u8 = 0x03; -pub const IMAGE_SYM_CLASS_REGISTER: u8 = 0x04; -pub const IMAGE_SYM_CLASS_EXTERNAL_DEF: u8 = 0x05; -pub const IMAGE_SYM_CLASS_LABEL: u8 = 0x06; -pub const IMAGE_SYM_CLASS_UNDEFINED_LABEL: u8 = 0x07; -pub const IMAGE_SYM_CLASS_MEMBER_OF_STRUCT: u8 = 0x08; -pub const IMAGE_SYM_CLASS_ARGUMENT: u8 = 0x09; -pub const IMAGE_SYM_CLASS_STRUCT_TAG: u8 = 0x0A; -pub const IMAGE_SYM_CLASS_MEMBER_OF_UNION: u8 = 0x0B; -pub const IMAGE_SYM_CLASS_UNION_TAG: u8 = 0x0C; -pub const IMAGE_SYM_CLASS_TYPE_DEFINITION: u8 = 0x0D; -pub const IMAGE_SYM_CLASS_UNDEFINED_STATIC: u8 = 0x0E; -pub const IMAGE_SYM_CLASS_ENUM_TAG: u8 = 0x0F; -pub const IMAGE_SYM_CLASS_MEMBER_OF_ENUM: u8 = 0x10; -pub const IMAGE_SYM_CLASS_REGISTER_PARAM: u8 = 0x11; -pub const IMAGE_SYM_CLASS_BIT_FIELD: u8 = 0x12; - -pub const IMAGE_SYM_CLASS_FAR_EXTERNAL: u8 = 0x44; - -pub const IMAGE_SYM_CLASS_BLOCK: u8 = 0x64; -pub const IMAGE_SYM_CLASS_FUNCTION: u8 = 0x65; -pub const IMAGE_SYM_CLASS_END_OF_STRUCT: u8 = 0x66; -pub const IMAGE_SYM_CLASS_FILE: u8 = 0x67; -// new -pub const IMAGE_SYM_CLASS_SECTION: u8 = 0x68; -pub const IMAGE_SYM_CLASS_WEAK_EXTERNAL: u8 = 0x69; - -pub const IMAGE_SYM_CLASS_CLR_TOKEN: u8 = 0x6B; - -// type packing constants - -pub const N_BTMASK: u16 = 0x000F; -pub const N_TMASK: u16 = 0x0030; -pub const N_TMASK1: u16 = 0x00C0; -pub const N_TMASK2: u16 = 0x00F0; -pub const N_BTSHFT: usize = 4; -pub const N_TSHIFT: usize = 2; - -pub const IMAGE_SYM_DTYPE_SHIFT: usize = N_BTSHFT; - -// -// Auxiliary entry format. -// - -// Used for both ImageSymbol and ImageSymbolEx (with padding). -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolTokenDef { - /// IMAGE_AUX_SYMBOL_TYPE - pub aux_type: u8, - /// Must be 0 - pub reserved1: u8, - pub symbol_table_index: U32Bytes, - /// Must be 0 - pub reserved2: [u8; 12], -} - -pub const IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF: u16 = 1; - -/// Auxiliary symbol format 1: function definitions. -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolFunction { - pub tag_index: U32Bytes, - pub total_size: U32Bytes, - pub pointer_to_linenumber: U32Bytes, - pub pointer_to_next_function: U32Bytes, - pub unused: [u8; 2], -} - -/// Auxiliary symbol format 2: .bf and .ef symbols. -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolFunctionBeginEnd { - pub unused1: [u8; 4], - /// declaration line number - pub linenumber: U16Bytes, - pub unused2: [u8; 6], - pub pointer_to_next_function: U32Bytes, - pub unused3: [u8; 2], -} - -/// Auxiliary symbol format 3: weak externals. -/// -/// Used for both `ImageSymbol` and `ImageSymbolEx` (both with padding). -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolWeak { - /// the weak extern default symbol index - pub weak_default_sym_index: U32Bytes, - pub weak_search_type: U32Bytes, -} - -/// Auxiliary symbol format 5: sections. -/// -/// Used for both `ImageSymbol` and `ImageSymbolEx` (with padding). -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolSection { - /// section length - pub length: U32Bytes, - /// number of relocation entries - pub number_of_relocations: U16Bytes, - /// number of line numbers - pub number_of_linenumbers: U16Bytes, - /// checksum for communal - pub check_sum: U32Bytes, - /// section number to associate with - pub number: U16Bytes, - /// communal selection type - pub selection: u8, - pub reserved: u8, - /// high bits of the section number - pub high_number: U16Bytes, -} - -// Used for both ImageSymbol and ImageSymbolEx (both with padding). -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAuxSymbolCrc { - pub crc: U32Bytes, -} - -// -// Communal selection types. -// - -pub const IMAGE_COMDAT_SELECT_NODUPLICATES: u8 = 1; -pub const IMAGE_COMDAT_SELECT_ANY: u8 = 2; -pub const IMAGE_COMDAT_SELECT_SAME_SIZE: u8 = 3; -pub const IMAGE_COMDAT_SELECT_EXACT_MATCH: u8 = 4; -pub const IMAGE_COMDAT_SELECT_ASSOCIATIVE: u8 = 5; -pub const IMAGE_COMDAT_SELECT_LARGEST: u8 = 6; -pub const IMAGE_COMDAT_SELECT_NEWEST: u8 = 7; - -pub const IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY: u16 = 1; -pub const IMAGE_WEAK_EXTERN_SEARCH_LIBRARY: u16 = 2; -pub const IMAGE_WEAK_EXTERN_SEARCH_ALIAS: u16 = 3; -pub const IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY: u16 = 4; - -// -// Relocation format. -// - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageRelocation { - /// Also `RelocCount` when IMAGE_SCN_LNK_NRELOC_OVFL is set - pub virtual_address: U32Bytes, - pub symbol_table_index: U32Bytes, - pub typ: U16Bytes, -} - -// -// I386 relocation types. -// -/// Reference is absolute, no relocation is necessary -pub const IMAGE_REL_I386_ABSOLUTE: u16 = 0x0000; -/// Direct 16-bit reference to the symbols virtual address -pub const IMAGE_REL_I386_DIR16: u16 = 0x0001; -/// PC-relative 16-bit reference to the symbols virtual address -pub const IMAGE_REL_I386_REL16: u16 = 0x0002; -/// Direct 32-bit reference to the symbols virtual address -pub const IMAGE_REL_I386_DIR32: u16 = 0x0006; -/// Direct 32-bit reference to the symbols virtual address, base not included -pub const IMAGE_REL_I386_DIR32NB: u16 = 0x0007; -/// Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address -pub const IMAGE_REL_I386_SEG12: u16 = 0x0009; -pub const IMAGE_REL_I386_SECTION: u16 = 0x000A; -pub const IMAGE_REL_I386_SECREL: u16 = 0x000B; -/// clr token -pub const IMAGE_REL_I386_TOKEN: u16 = 0x000C; -/// 7 bit offset from base of section containing target -pub const IMAGE_REL_I386_SECREL7: u16 = 0x000D; -/// PC-relative 32-bit reference to the symbols virtual address -pub const IMAGE_REL_I386_REL32: u16 = 0x0014; - -// -// MIPS relocation types. -// -/// Reference is absolute, no relocation is necessary -pub const IMAGE_REL_MIPS_ABSOLUTE: u16 = 0x0000; -pub const IMAGE_REL_MIPS_REFHALF: u16 = 0x0001; -pub const IMAGE_REL_MIPS_REFWORD: u16 = 0x0002; -pub const IMAGE_REL_MIPS_JMPADDR: u16 = 0x0003; -pub const IMAGE_REL_MIPS_REFHI: u16 = 0x0004; -pub const IMAGE_REL_MIPS_REFLO: u16 = 0x0005; -pub const IMAGE_REL_MIPS_GPREL: u16 = 0x0006; -pub const IMAGE_REL_MIPS_LITERAL: u16 = 0x0007; -pub const IMAGE_REL_MIPS_SECTION: u16 = 0x000A; -pub const IMAGE_REL_MIPS_SECREL: u16 = 0x000B; -/// Low 16-bit section relative reference (used for >32k TLS) -pub const IMAGE_REL_MIPS_SECRELLO: u16 = 0x000C; -/// High 16-bit section relative reference (used for >32k TLS) -pub const IMAGE_REL_MIPS_SECRELHI: u16 = 0x000D; -/// clr token -pub const IMAGE_REL_MIPS_TOKEN: u16 = 0x000E; -pub const IMAGE_REL_MIPS_JMPADDR16: u16 = 0x0010; -pub const IMAGE_REL_MIPS_REFWORDNB: u16 = 0x0022; -pub const IMAGE_REL_MIPS_PAIR: u16 = 0x0025; - -// -// Alpha Relocation types. -// -pub const IMAGE_REL_ALPHA_ABSOLUTE: u16 = 0x0000; -pub const IMAGE_REL_ALPHA_REFLONG: u16 = 0x0001; -pub const IMAGE_REL_ALPHA_REFQUAD: u16 = 0x0002; -pub const IMAGE_REL_ALPHA_GPREL32: u16 = 0x0003; -pub const IMAGE_REL_ALPHA_LITERAL: u16 = 0x0004; -pub const IMAGE_REL_ALPHA_LITUSE: u16 = 0x0005; -pub const IMAGE_REL_ALPHA_GPDISP: u16 = 0x0006; -pub const IMAGE_REL_ALPHA_BRADDR: u16 = 0x0007; -pub const IMAGE_REL_ALPHA_HINT: u16 = 0x0008; -pub const IMAGE_REL_ALPHA_INLINE_REFLONG: u16 = 0x0009; -pub const IMAGE_REL_ALPHA_REFHI: u16 = 0x000A; -pub const IMAGE_REL_ALPHA_REFLO: u16 = 0x000B; -pub const IMAGE_REL_ALPHA_PAIR: u16 = 0x000C; -pub const IMAGE_REL_ALPHA_MATCH: u16 = 0x000D; -pub const IMAGE_REL_ALPHA_SECTION: u16 = 0x000E; -pub const IMAGE_REL_ALPHA_SECREL: u16 = 0x000F; -pub const IMAGE_REL_ALPHA_REFLONGNB: u16 = 0x0010; -/// Low 16-bit section relative reference -pub const IMAGE_REL_ALPHA_SECRELLO: u16 = 0x0011; -/// High 16-bit section relative reference -pub const IMAGE_REL_ALPHA_SECRELHI: u16 = 0x0012; -/// High 16 bits of 48 bit reference -pub const IMAGE_REL_ALPHA_REFQ3: u16 = 0x0013; -/// Middle 16 bits of 48 bit reference -pub const IMAGE_REL_ALPHA_REFQ2: u16 = 0x0014; -/// Low 16 bits of 48 bit reference -pub const IMAGE_REL_ALPHA_REFQ1: u16 = 0x0015; -/// Low 16-bit GP relative reference -pub const IMAGE_REL_ALPHA_GPRELLO: u16 = 0x0016; -/// High 16-bit GP relative reference -pub const IMAGE_REL_ALPHA_GPRELHI: u16 = 0x0017; - -// -// IBM PowerPC relocation types. -// -/// NOP -pub const IMAGE_REL_PPC_ABSOLUTE: u16 = 0x0000; -/// 64-bit address -pub const IMAGE_REL_PPC_ADDR64: u16 = 0x0001; -/// 32-bit address -pub const IMAGE_REL_PPC_ADDR32: u16 = 0x0002; -/// 26-bit address, shifted left 2 (branch absolute) -pub const IMAGE_REL_PPC_ADDR24: u16 = 0x0003; -/// 16-bit address -pub const IMAGE_REL_PPC_ADDR16: u16 = 0x0004; -/// 16-bit address, shifted left 2 (load doubleword) -pub const IMAGE_REL_PPC_ADDR14: u16 = 0x0005; -/// 26-bit PC-relative offset, shifted left 2 (branch relative) -pub const IMAGE_REL_PPC_REL24: u16 = 0x0006; -/// 16-bit PC-relative offset, shifted left 2 (br cond relative) -pub const IMAGE_REL_PPC_REL14: u16 = 0x0007; -/// 16-bit offset from TOC base -pub const IMAGE_REL_PPC_TOCREL16: u16 = 0x0008; -/// 16-bit offset from TOC base, shifted left 2 (load doubleword) -pub const IMAGE_REL_PPC_TOCREL14: u16 = 0x0009; - -/// 32-bit addr w/o image base -pub const IMAGE_REL_PPC_ADDR32NB: u16 = 0x000A; -/// va of containing section (as in an image sectionhdr) -pub const IMAGE_REL_PPC_SECREL: u16 = 0x000B; -/// sectionheader number -pub const IMAGE_REL_PPC_SECTION: u16 = 0x000C; -/// substitute TOC restore instruction iff symbol is glue code -pub const IMAGE_REL_PPC_IFGLUE: u16 = 0x000D; -/// symbol is glue code; virtual address is TOC restore instruction -pub const IMAGE_REL_PPC_IMGLUE: u16 = 0x000E; -/// va of containing section (limited to 16 bits) -pub const IMAGE_REL_PPC_SECREL16: u16 = 0x000F; -pub const IMAGE_REL_PPC_REFHI: u16 = 0x0010; -pub const IMAGE_REL_PPC_REFLO: u16 = 0x0011; -pub const IMAGE_REL_PPC_PAIR: u16 = 0x0012; -/// Low 16-bit section relative reference (used for >32k TLS) -pub const IMAGE_REL_PPC_SECRELLO: u16 = 0x0013; -/// High 16-bit section relative reference (used for >32k TLS) -pub const IMAGE_REL_PPC_SECRELHI: u16 = 0x0014; -pub const IMAGE_REL_PPC_GPREL: u16 = 0x0015; -/// clr token -pub const IMAGE_REL_PPC_TOKEN: u16 = 0x0016; - -/// mask to isolate above values in IMAGE_RELOCATION.Type -pub const IMAGE_REL_PPC_TYPEMASK: u16 = 0x00FF; - -// Flag bits in `ImageRelocation::typ`. - -/// subtract reloc value rather than adding it -pub const IMAGE_REL_PPC_NEG: u16 = 0x0100; -/// fix branch prediction bit to predict branch taken -pub const IMAGE_REL_PPC_BRTAKEN: u16 = 0x0200; -/// fix branch prediction bit to predict branch not taken -pub const IMAGE_REL_PPC_BRNTAKEN: u16 = 0x0400; -/// toc slot defined in file (or, data in toc) -pub const IMAGE_REL_PPC_TOCDEFN: u16 = 0x0800; - -// -// Hitachi SH3 relocation types. -// -/// No relocation -pub const IMAGE_REL_SH3_ABSOLUTE: u16 = 0x0000; -/// 16 bit direct -pub const IMAGE_REL_SH3_DIRECT16: u16 = 0x0001; -/// 32 bit direct -pub const IMAGE_REL_SH3_DIRECT32: u16 = 0x0002; -/// 8 bit direct, -128..255 -pub const IMAGE_REL_SH3_DIRECT8: u16 = 0x0003; -/// 8 bit direct .W (0 ext.) -pub const IMAGE_REL_SH3_DIRECT8_WORD: u16 = 0x0004; -/// 8 bit direct .L (0 ext.) -pub const IMAGE_REL_SH3_DIRECT8_LONG: u16 = 0x0005; -/// 4 bit direct (0 ext.) -pub const IMAGE_REL_SH3_DIRECT4: u16 = 0x0006; -/// 4 bit direct .W (0 ext.) -pub const IMAGE_REL_SH3_DIRECT4_WORD: u16 = 0x0007; -/// 4 bit direct .L (0 ext.) -pub const IMAGE_REL_SH3_DIRECT4_LONG: u16 = 0x0008; -/// 8 bit PC relative .W -pub const IMAGE_REL_SH3_PCREL8_WORD: u16 = 0x0009; -/// 8 bit PC relative .L -pub const IMAGE_REL_SH3_PCREL8_LONG: u16 = 0x000A; -/// 12 LSB PC relative .W -pub const IMAGE_REL_SH3_PCREL12_WORD: u16 = 0x000B; -/// Start of EXE section -pub const IMAGE_REL_SH3_STARTOF_SECTION: u16 = 0x000C; -/// Size of EXE section -pub const IMAGE_REL_SH3_SIZEOF_SECTION: u16 = 0x000D; -/// Section table index -pub const IMAGE_REL_SH3_SECTION: u16 = 0x000E; -/// Offset within section -pub const IMAGE_REL_SH3_SECREL: u16 = 0x000F; -/// 32 bit direct not based -pub const IMAGE_REL_SH3_DIRECT32_NB: u16 = 0x0010; -/// GP-relative addressing -pub const IMAGE_REL_SH3_GPREL4_LONG: u16 = 0x0011; -/// clr token -pub const IMAGE_REL_SH3_TOKEN: u16 = 0x0012; -/// Offset from current instruction in longwords -/// if not NOMODE, insert the inverse of the low bit at bit 32 to select PTA/PTB -pub const IMAGE_REL_SHM_PCRELPT: u16 = 0x0013; -/// Low bits of 32-bit address -pub const IMAGE_REL_SHM_REFLO: u16 = 0x0014; -/// High bits of 32-bit address -pub const IMAGE_REL_SHM_REFHALF: u16 = 0x0015; -/// Low bits of relative reference -pub const IMAGE_REL_SHM_RELLO: u16 = 0x0016; -/// High bits of relative reference -pub const IMAGE_REL_SHM_RELHALF: u16 = 0x0017; -/// offset operand for relocation -pub const IMAGE_REL_SHM_PAIR: u16 = 0x0018; - -/// relocation ignores section mode -pub const IMAGE_REL_SH_NOMODE: u16 = 0x8000; - -/// No relocation required -pub const IMAGE_REL_ARM_ABSOLUTE: u16 = 0x0000; -/// 32 bit address -pub const IMAGE_REL_ARM_ADDR32: u16 = 0x0001; -/// 32 bit address w/o image base -pub const IMAGE_REL_ARM_ADDR32NB: u16 = 0x0002; -/// 24 bit offset << 2 & sign ext. -pub const IMAGE_REL_ARM_BRANCH24: u16 = 0x0003; -/// Thumb: 2 11 bit offsets -pub const IMAGE_REL_ARM_BRANCH11: u16 = 0x0004; -/// clr token -pub const IMAGE_REL_ARM_TOKEN: u16 = 0x0005; -/// GP-relative addressing (ARM) -pub const IMAGE_REL_ARM_GPREL12: u16 = 0x0006; -/// GP-relative addressing (Thumb) -pub const IMAGE_REL_ARM_GPREL7: u16 = 0x0007; -pub const IMAGE_REL_ARM_BLX24: u16 = 0x0008; -pub const IMAGE_REL_ARM_BLX11: u16 = 0x0009; -/// 32-bit relative address from byte following reloc -pub const IMAGE_REL_ARM_REL32: u16 = 0x000A; -/// Section table index -pub const IMAGE_REL_ARM_SECTION: u16 = 0x000E; -/// Offset within section -pub const IMAGE_REL_ARM_SECREL: u16 = 0x000F; -/// ARM: MOVW/MOVT -pub const IMAGE_REL_ARM_MOV32A: u16 = 0x0010; -/// ARM: MOVW/MOVT (deprecated) -pub const IMAGE_REL_ARM_MOV32: u16 = 0x0010; -/// Thumb: MOVW/MOVT -pub const IMAGE_REL_ARM_MOV32T: u16 = 0x0011; -/// Thumb: MOVW/MOVT (deprecated) -pub const IMAGE_REL_THUMB_MOV32: u16 = 0x0011; -/// Thumb: 32-bit conditional B -pub const IMAGE_REL_ARM_BRANCH20T: u16 = 0x0012; -/// Thumb: 32-bit conditional B (deprecated) -pub const IMAGE_REL_THUMB_BRANCH20: u16 = 0x0012; -/// Thumb: 32-bit B or BL -pub const IMAGE_REL_ARM_BRANCH24T: u16 = 0x0014; -/// Thumb: 32-bit B or BL (deprecated) -pub const IMAGE_REL_THUMB_BRANCH24: u16 = 0x0014; -/// Thumb: BLX immediate -pub const IMAGE_REL_ARM_BLX23T: u16 = 0x0015; -/// Thumb: BLX immediate (deprecated) -pub const IMAGE_REL_THUMB_BLX23: u16 = 0x0015; - -pub const IMAGE_REL_AM_ABSOLUTE: u16 = 0x0000; -pub const IMAGE_REL_AM_ADDR32: u16 = 0x0001; -pub const IMAGE_REL_AM_ADDR32NB: u16 = 0x0002; -pub const IMAGE_REL_AM_CALL32: u16 = 0x0003; -pub const IMAGE_REL_AM_FUNCINFO: u16 = 0x0004; -pub const IMAGE_REL_AM_REL32_1: u16 = 0x0005; -pub const IMAGE_REL_AM_REL32_2: u16 = 0x0006; -pub const IMAGE_REL_AM_SECREL: u16 = 0x0007; -pub const IMAGE_REL_AM_SECTION: u16 = 0x0008; -pub const IMAGE_REL_AM_TOKEN: u16 = 0x0009; - -// -// ARM64 relocations types. -// - -/// No relocation required -pub const IMAGE_REL_ARM64_ABSOLUTE: u16 = 0x0000; -/// 32 bit address. Review! do we need it? -pub const IMAGE_REL_ARM64_ADDR32: u16 = 0x0001; -/// 32 bit address w/o image base (RVA: for Data/PData/XData) -pub const IMAGE_REL_ARM64_ADDR32NB: u16 = 0x0002; -/// 26 bit offset << 2 & sign ext. for B & BL -pub const IMAGE_REL_ARM64_BRANCH26: u16 = 0x0003; -/// ADRP -pub const IMAGE_REL_ARM64_PAGEBASE_REL21: u16 = 0x0004; -/// ADR -pub const IMAGE_REL_ARM64_REL21: u16 = 0x0005; -/// ADD/ADDS (immediate) with zero shift, for page offset -pub const IMAGE_REL_ARM64_PAGEOFFSET_12A: u16 = 0x0006; -/// LDR (indexed, unsigned immediate), for page offset -pub const IMAGE_REL_ARM64_PAGEOFFSET_12L: u16 = 0x0007; -/// Offset within section -pub const IMAGE_REL_ARM64_SECREL: u16 = 0x0008; -/// ADD/ADDS (immediate) with zero shift, for bit 0:11 of section offset -pub const IMAGE_REL_ARM64_SECREL_LOW12A: u16 = 0x0009; -/// ADD/ADDS (immediate) with zero shift, for bit 12:23 of section offset -pub const IMAGE_REL_ARM64_SECREL_HIGH12A: u16 = 0x000A; -/// LDR (indexed, unsigned immediate), for bit 0:11 of section offset -pub const IMAGE_REL_ARM64_SECREL_LOW12L: u16 = 0x000B; -pub const IMAGE_REL_ARM64_TOKEN: u16 = 0x000C; -/// Section table index -pub const IMAGE_REL_ARM64_SECTION: u16 = 0x000D; -/// 64 bit address -pub const IMAGE_REL_ARM64_ADDR64: u16 = 0x000E; -/// 19 bit offset << 2 & sign ext. for conditional B -pub const IMAGE_REL_ARM64_BRANCH19: u16 = 0x000F; -/// TBZ/TBNZ -pub const IMAGE_REL_ARM64_BRANCH14: u16 = 0x0010; -/// 32-bit relative address from byte following reloc -pub const IMAGE_REL_ARM64_REL32: u16 = 0x0011; - -// -// x64 relocations -// -/// Reference is absolute, no relocation is necessary -pub const IMAGE_REL_AMD64_ABSOLUTE: u16 = 0x0000; -/// 64-bit address (VA). -pub const IMAGE_REL_AMD64_ADDR64: u16 = 0x0001; -/// 32-bit address (VA). -pub const IMAGE_REL_AMD64_ADDR32: u16 = 0x0002; -/// 32-bit address w/o image base (RVA). -pub const IMAGE_REL_AMD64_ADDR32NB: u16 = 0x0003; -/// 32-bit relative address from byte following reloc -pub const IMAGE_REL_AMD64_REL32: u16 = 0x0004; -/// 32-bit relative address from byte distance 1 from reloc -pub const IMAGE_REL_AMD64_REL32_1: u16 = 0x0005; -/// 32-bit relative address from byte distance 2 from reloc -pub const IMAGE_REL_AMD64_REL32_2: u16 = 0x0006; -/// 32-bit relative address from byte distance 3 from reloc -pub const IMAGE_REL_AMD64_REL32_3: u16 = 0x0007; -/// 32-bit relative address from byte distance 4 from reloc -pub const IMAGE_REL_AMD64_REL32_4: u16 = 0x0008; -/// 32-bit relative address from byte distance 5 from reloc -pub const IMAGE_REL_AMD64_REL32_5: u16 = 0x0009; -/// Section index -pub const IMAGE_REL_AMD64_SECTION: u16 = 0x000A; -/// 32 bit offset from base of section containing target -pub const IMAGE_REL_AMD64_SECREL: u16 = 0x000B; -/// 7 bit unsigned offset from base of section containing target -pub const IMAGE_REL_AMD64_SECREL7: u16 = 0x000C; -/// 32 bit metadata token -pub const IMAGE_REL_AMD64_TOKEN: u16 = 0x000D; -/// 32 bit signed span-dependent value emitted into object -pub const IMAGE_REL_AMD64_SREL32: u16 = 0x000E; -pub const IMAGE_REL_AMD64_PAIR: u16 = 0x000F; -/// 32 bit signed span-dependent value applied at link time -pub const IMAGE_REL_AMD64_SSPAN32: u16 = 0x0010; -pub const IMAGE_REL_AMD64_EHANDLER: u16 = 0x0011; -/// Indirect branch to an import -pub const IMAGE_REL_AMD64_IMPORT_BR: u16 = 0x0012; -/// Indirect call to an import -pub const IMAGE_REL_AMD64_IMPORT_CALL: u16 = 0x0013; -/// Indirect branch to a CFG check -pub const IMAGE_REL_AMD64_CFG_BR: u16 = 0x0014; -/// Indirect branch to a CFG check, with REX.W prefix -pub const IMAGE_REL_AMD64_CFG_BR_REX: u16 = 0x0015; -/// Indirect call to a CFG check -pub const IMAGE_REL_AMD64_CFG_CALL: u16 = 0x0016; -/// Indirect branch to a target in RAX (no CFG) -pub const IMAGE_REL_AMD64_INDIR_BR: u16 = 0x0017; -/// Indirect branch to a target in RAX, with REX.W prefix (no CFG) -pub const IMAGE_REL_AMD64_INDIR_BR_REX: u16 = 0x0018; -/// Indirect call to a target in RAX (no CFG) -pub const IMAGE_REL_AMD64_INDIR_CALL: u16 = 0x0019; -/// Indirect branch for a switch table using Reg 0 (RAX) -pub const IMAGE_REL_AMD64_INDIR_BR_SWITCHTABLE_FIRST: u16 = 0x0020; -/// Indirect branch for a switch table using Reg 15 (R15) -pub const IMAGE_REL_AMD64_INDIR_BR_SWITCHTABLE_LAST: u16 = 0x002F; - -// -// IA64 relocation types. -// -pub const IMAGE_REL_IA64_ABSOLUTE: u16 = 0x0000; -pub const IMAGE_REL_IA64_IMM14: u16 = 0x0001; -pub const IMAGE_REL_IA64_IMM22: u16 = 0x0002; -pub const IMAGE_REL_IA64_IMM64: u16 = 0x0003; -pub const IMAGE_REL_IA64_DIR32: u16 = 0x0004; -pub const IMAGE_REL_IA64_DIR64: u16 = 0x0005; -pub const IMAGE_REL_IA64_PCREL21B: u16 = 0x0006; -pub const IMAGE_REL_IA64_PCREL21M: u16 = 0x0007; -pub const IMAGE_REL_IA64_PCREL21F: u16 = 0x0008; -pub const IMAGE_REL_IA64_GPREL22: u16 = 0x0009; -pub const IMAGE_REL_IA64_LTOFF22: u16 = 0x000A; -pub const IMAGE_REL_IA64_SECTION: u16 = 0x000B; -pub const IMAGE_REL_IA64_SECREL22: u16 = 0x000C; -pub const IMAGE_REL_IA64_SECREL64I: u16 = 0x000D; -pub const IMAGE_REL_IA64_SECREL32: u16 = 0x000E; -// -pub const IMAGE_REL_IA64_DIR32NB: u16 = 0x0010; -pub const IMAGE_REL_IA64_SREL14: u16 = 0x0011; -pub const IMAGE_REL_IA64_SREL22: u16 = 0x0012; -pub const IMAGE_REL_IA64_SREL32: u16 = 0x0013; -pub const IMAGE_REL_IA64_UREL32: u16 = 0x0014; -/// This is always a BRL and never converted -pub const IMAGE_REL_IA64_PCREL60X: u16 = 0x0015; -/// If possible, convert to MBB bundle with NOP.B in slot 1 -pub const IMAGE_REL_IA64_PCREL60B: u16 = 0x0016; -/// If possible, convert to MFB bundle with NOP.F in slot 1 -pub const IMAGE_REL_IA64_PCREL60F: u16 = 0x0017; -/// If possible, convert to MIB bundle with NOP.I in slot 1 -pub const IMAGE_REL_IA64_PCREL60I: u16 = 0x0018; -/// If possible, convert to MMB bundle with NOP.M in slot 1 -pub const IMAGE_REL_IA64_PCREL60M: u16 = 0x0019; -pub const IMAGE_REL_IA64_IMMGPREL64: u16 = 0x001A; -/// clr token -pub const IMAGE_REL_IA64_TOKEN: u16 = 0x001B; -pub const IMAGE_REL_IA64_GPREL32: u16 = 0x001C; -pub const IMAGE_REL_IA64_ADDEND: u16 = 0x001F; - -// -// CEF relocation types. -// -/// Reference is absolute, no relocation is necessary -pub const IMAGE_REL_CEF_ABSOLUTE: u16 = 0x0000; -/// 32-bit address (VA). -pub const IMAGE_REL_CEF_ADDR32: u16 = 0x0001; -/// 64-bit address (VA). -pub const IMAGE_REL_CEF_ADDR64: u16 = 0x0002; -/// 32-bit address w/o image base (RVA). -pub const IMAGE_REL_CEF_ADDR32NB: u16 = 0x0003; -/// Section index -pub const IMAGE_REL_CEF_SECTION: u16 = 0x0004; -/// 32 bit offset from base of section containing target -pub const IMAGE_REL_CEF_SECREL: u16 = 0x0005; -/// 32 bit metadata token -pub const IMAGE_REL_CEF_TOKEN: u16 = 0x0006; - -// -// clr relocation types. -// -/// Reference is absolute, no relocation is necessary -pub const IMAGE_REL_CEE_ABSOLUTE: u16 = 0x0000; -/// 32-bit address (VA). -pub const IMAGE_REL_CEE_ADDR32: u16 = 0x0001; -/// 64-bit address (VA). -pub const IMAGE_REL_CEE_ADDR64: u16 = 0x0002; -/// 32-bit address w/o image base (RVA). -pub const IMAGE_REL_CEE_ADDR32NB: u16 = 0x0003; -/// Section index -pub const IMAGE_REL_CEE_SECTION: u16 = 0x0004; -/// 32 bit offset from base of section containing target -pub const IMAGE_REL_CEE_SECREL: u16 = 0x0005; -/// 32 bit metadata token -pub const IMAGE_REL_CEE_TOKEN: u16 = 0x0006; - -/// No relocation required -pub const IMAGE_REL_M32R_ABSOLUTE: u16 = 0x0000; -/// 32 bit address -pub const IMAGE_REL_M32R_ADDR32: u16 = 0x0001; -/// 32 bit address w/o image base -pub const IMAGE_REL_M32R_ADDR32NB: u16 = 0x0002; -/// 24 bit address -pub const IMAGE_REL_M32R_ADDR24: u16 = 0x0003; -/// GP relative addressing -pub const IMAGE_REL_M32R_GPREL16: u16 = 0x0004; -/// 24 bit offset << 2 & sign ext. -pub const IMAGE_REL_M32R_PCREL24: u16 = 0x0005; -/// 16 bit offset << 2 & sign ext. -pub const IMAGE_REL_M32R_PCREL16: u16 = 0x0006; -/// 8 bit offset << 2 & sign ext. -pub const IMAGE_REL_M32R_PCREL8: u16 = 0x0007; -/// 16 MSBs -pub const IMAGE_REL_M32R_REFHALF: u16 = 0x0008; -/// 16 MSBs; adj for LSB sign ext. -pub const IMAGE_REL_M32R_REFHI: u16 = 0x0009; -/// 16 LSBs -pub const IMAGE_REL_M32R_REFLO: u16 = 0x000A; -/// Link HI and LO -pub const IMAGE_REL_M32R_PAIR: u16 = 0x000B; -/// Section table index -pub const IMAGE_REL_M32R_SECTION: u16 = 0x000C; -/// 32 bit section relative reference -pub const IMAGE_REL_M32R_SECREL32: u16 = 0x000D; -/// clr token -pub const IMAGE_REL_M32R_TOKEN: u16 = 0x000E; - -/// No relocation required -pub const IMAGE_REL_EBC_ABSOLUTE: u16 = 0x0000; -/// 32 bit address w/o image base -pub const IMAGE_REL_EBC_ADDR32NB: u16 = 0x0001; -/// 32-bit relative address from byte following reloc -pub const IMAGE_REL_EBC_REL32: u16 = 0x0002; -/// Section table index -pub const IMAGE_REL_EBC_SECTION: u16 = 0x0003; -/// Offset within section -pub const IMAGE_REL_EBC_SECREL: u16 = 0x0004; - -/* -// TODO? -#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) /* Intel-IA64-Filler */ \ - Value |= (((ULONGLONG)((*(Address) >> InstPos) & (((ULONGLONG)1 << Size) - 1))) << ValPos) // Intel-IA64-Filler - -#define INS_IMM64(Value, Address, Size, InstPos, ValPos) /* Intel-IA64-Filler */\ - *(PDWORD)Address = (*(PDWORD)Address & ~(((1 << Size) - 1) << InstPos)) | /* Intel-IA64-Filler */\ - ((DWORD)((((ULONGLONG)Value >> ValPos) & (((ULONGLONG)1 << Size) - 1))) << InstPos) // Intel-IA64-Filler -*/ - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM7B_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM7B_SIZE_X: u16 = 7; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X: u16 = 4; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM7B_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM9D_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM9D_SIZE_X: u16 = 9; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X: u16 = 18; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM9D_VAL_POS_X: u16 = 7; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM5C_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM5C_SIZE_X: u16 = 5; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X: u16 = 13; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM5C_VAL_POS_X: u16 = 16; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IC_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IC_SIZE_X: u16 = 1; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IC_INST_WORD_POS_X: u16 = 12; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IC_VAL_POS_X: u16 = 21; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41A_INST_WORD_X: u16 = 1; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41A_SIZE_X: u16 = 10; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41A_INST_WORD_POS_X: u16 = 14; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41A_VAL_POS_X: u16 = 22; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41B_INST_WORD_X: u16 = 1; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41B_SIZE_X: u16 = 8; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41B_INST_WORD_POS_X: u16 = 24; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41B_VAL_POS_X: u16 = 32; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41C_INST_WORD_X: u16 = 2; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41C_SIZE_X: u16 = 23; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41C_INST_WORD_POS_X: u16 = 0; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_IMM41C_VAL_POS_X: u16 = 40; - -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_SIGN_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_SIGN_SIZE_X: u16 = 1; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_SIGN_INST_WORD_POS_X: u16 = 27; -/// Intel-IA64-Filler -pub const EMARCH_ENC_I17_SIGN_VAL_POS_X: u16 = 63; - -/// Intel-IA64-Filler -pub const X3_OPCODE_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_OPCODE_SIZE_X: u16 = 4; -/// Intel-IA64-Filler -pub const X3_OPCODE_INST_WORD_POS_X: u16 = 28; -/// Intel-IA64-Filler -pub const X3_OPCODE_SIGN_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_I_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_I_SIZE_X: u16 = 1; -/// Intel-IA64-Filler -pub const X3_I_INST_WORD_POS_X: u16 = 27; -/// Intel-IA64-Filler -pub const X3_I_SIGN_VAL_POS_X: u16 = 59; - -/// Intel-IA64-Filler -pub const X3_D_WH_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_D_WH_SIZE_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_D_WH_INST_WORD_POS_X: u16 = 24; -/// Intel-IA64-Filler -pub const X3_D_WH_SIGN_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_IMM20_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_IMM20_SIZE_X: u16 = 20; -/// Intel-IA64-Filler -pub const X3_IMM20_INST_WORD_POS_X: u16 = 4; -/// Intel-IA64-Filler -pub const X3_IMM20_SIGN_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_IMM39_1_INST_WORD_X: u16 = 2; -/// Intel-IA64-Filler -pub const X3_IMM39_1_SIZE_X: u16 = 23; -/// Intel-IA64-Filler -pub const X3_IMM39_1_INST_WORD_POS_X: u16 = 0; -/// Intel-IA64-Filler -pub const X3_IMM39_1_SIGN_VAL_POS_X: u16 = 36; - -/// Intel-IA64-Filler -pub const X3_IMM39_2_INST_WORD_X: u16 = 1; -/// Intel-IA64-Filler -pub const X3_IMM39_2_SIZE_X: u16 = 16; -/// Intel-IA64-Filler -pub const X3_IMM39_2_INST_WORD_POS_X: u16 = 16; -/// Intel-IA64-Filler -pub const X3_IMM39_2_SIGN_VAL_POS_X: u16 = 20; - -/// Intel-IA64-Filler -pub const X3_P_INST_WORD_X: u16 = 3; -/// Intel-IA64-Filler -pub const X3_P_SIZE_X: u16 = 4; -/// Intel-IA64-Filler -pub const X3_P_INST_WORD_POS_X: u16 = 0; -/// Intel-IA64-Filler -pub const X3_P_SIGN_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_TMPLT_INST_WORD_X: u16 = 0; -/// Intel-IA64-Filler -pub const X3_TMPLT_SIZE_X: u16 = 4; -/// Intel-IA64-Filler -pub const X3_TMPLT_INST_WORD_POS_X: u16 = 0; -/// Intel-IA64-Filler -pub const X3_TMPLT_SIGN_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_BTYPE_QP_INST_WORD_X: u16 = 2; -/// Intel-IA64-Filler -pub const X3_BTYPE_QP_SIZE_X: u16 = 9; -/// Intel-IA64-Filler -pub const X3_BTYPE_QP_INST_WORD_POS_X: u16 = 23; -/// Intel-IA64-Filler -pub const X3_BTYPE_QP_INST_VAL_POS_X: u16 = 0; - -/// Intel-IA64-Filler -pub const X3_EMPTY_INST_WORD_X: u16 = 1; -/// Intel-IA64-Filler -pub const X3_EMPTY_SIZE_X: u16 = 2; -/// Intel-IA64-Filler -pub const X3_EMPTY_INST_WORD_POS_X: u16 = 14; -/// Intel-IA64-Filler -pub const X3_EMPTY_INST_VAL_POS_X: u16 = 0; - -// -// Line number format. -// - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageLinenumber { - /// Symbol table index of function name if Linenumber is 0. - /// Otherwise virtual address of line number. - pub symbol_table_index_or_virtual_address: U32Bytes, - /// Line number. - pub linenumber: U16Bytes, -} - -// -// Based relocation format. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageBaseRelocation { - pub virtual_address: U32, - pub size_of_block: U32, - // pub type_offset[1]: U16, -} - -// -// Based relocation types. -// - -pub const IMAGE_REL_BASED_ABSOLUTE: u16 = 0; -pub const IMAGE_REL_BASED_HIGH: u16 = 1; -pub const IMAGE_REL_BASED_LOW: u16 = 2; -pub const IMAGE_REL_BASED_HIGHLOW: u16 = 3; -pub const IMAGE_REL_BASED_HIGHADJ: u16 = 4; -pub const IMAGE_REL_BASED_MACHINE_SPECIFIC_5: u16 = 5; -pub const IMAGE_REL_BASED_RESERVED: u16 = 6; -pub const IMAGE_REL_BASED_MACHINE_SPECIFIC_7: u16 = 7; -pub const IMAGE_REL_BASED_MACHINE_SPECIFIC_8: u16 = 8; -pub const IMAGE_REL_BASED_MACHINE_SPECIFIC_9: u16 = 9; -pub const IMAGE_REL_BASED_DIR64: u16 = 10; - -// -// Platform-specific based relocation types. -// - -pub const IMAGE_REL_BASED_IA64_IMM64: u16 = 9; - -pub const IMAGE_REL_BASED_MIPS_JMPADDR: u16 = 5; -pub const IMAGE_REL_BASED_MIPS_JMPADDR16: u16 = 9; - -pub const IMAGE_REL_BASED_ARM_MOV32: u16 = 5; -pub const IMAGE_REL_BASED_THUMB_MOV32: u16 = 7; - -pub const IMAGE_REL_BASED_RISCV_HIGH20: u16 = 5; -pub const IMAGE_REL_BASED_RISCV_LOW12I: u16 = 7; -pub const IMAGE_REL_BASED_RISCV_LOW12S: u16 = 8; - -// -// Archive format. -// - -pub const IMAGE_ARCHIVE_START_SIZE: usize = 8; -pub const IMAGE_ARCHIVE_START: &[u8; 8] = b"!\n"; -pub const IMAGE_ARCHIVE_END: &[u8] = b"`\n"; -pub const IMAGE_ARCHIVE_PAD: &[u8] = b"\n"; -pub const IMAGE_ARCHIVE_LINKER_MEMBER: &[u8; 16] = b"/ "; -pub const IMAGE_ARCHIVE_LONGNAMES_MEMBER: &[u8; 16] = b"// "; -pub const IMAGE_ARCHIVE_HYBRIDMAP_MEMBER: &[u8; 16] = b"// "; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageArchiveMemberHeader { - /// File member name - `/' terminated. - pub name: [u8; 16], - /// File member date - decimal. - pub date: [u8; 12], - /// File member user id - decimal. - pub user_id: [u8; 6], - /// File member group id - decimal. - pub group_id: [u8; 6], - /// File member mode - octal. - pub mode: [u8; 8], - /// File member size - decimal. - pub size: [u8; 10], - /// String to end header. - pub end_header: [u8; 2], -} - -pub const IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR: u16 = 60; - -// -// DLL support. -// - -// -// Export Format -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageExportDirectory { - pub characteristics: U32, - pub time_date_stamp: U32, - pub major_version: U16, - pub minor_version: U16, - pub name: U32, - pub base: U32, - pub number_of_functions: U32, - pub number_of_names: U32, - /// RVA from base of image - pub address_of_functions: U32, - /// RVA from base of image - pub address_of_names: U32, - /// RVA from base of image - pub address_of_name_ordinals: U32, -} - -// -// Import Format -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageImportByName { - pub hint: U16, - //pub name: [i8; 1], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageThunkData64(pub U64); -/* - union { -/// PBYTE - pub forwarder_string: U64, -/// PDWORD - pub function: U64, - pub ordinal: U64, -/// PIMAGE_IMPORT_BY_NAME - pub address_of_data: U64, - } u1; -*/ - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageThunkData32(pub U32); -/* - union { -/// PBYTE - pub forwarder_string: U32, -/// PDWORD - pub function: U32, - pub ordinal: U32, -/// PIMAGE_IMPORT_BY_NAME - pub address_of_data: U32, - } u1; -} -*/ - -pub const IMAGE_ORDINAL_FLAG64: u64 = 0x8000000000000000; -pub const IMAGE_ORDINAL_FLAG32: u32 = 0x80000000; - -/* -#define IMAGE_ORDINAL64(Ordinal) (Ordinal & 0xffff) -#define IMAGE_ORDINAL32(Ordinal) (Ordinal & 0xffff) -#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) -#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0) - -*/ - -// -// Thread Local Storage -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageTlsDirectory64 { - pub start_address_of_raw_data: U64, - pub end_address_of_raw_data: U64, - /// PDWORD - pub address_of_index: U64, - /// PIMAGE_TLS_CALLBACK *; - pub address_of_call_backs: U64, - pub size_of_zero_fill: U32, - pub characteristics: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageTlsDirectory32 { - pub start_address_of_raw_data: U32, - pub end_address_of_raw_data: U32, - /// PDWORD - pub address_of_index: U32, - /// PIMAGE_TLS_CALLBACK * - pub address_of_call_backs: U32, - pub size_of_zero_fill: U32, - pub characteristics: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageImportDescriptor { - /// RVA to original unbound IAT (`ImageThunkData32`/`ImageThunkData64`) - /// 0 for terminating null import descriptor - pub original_first_thunk: U32Bytes, - /// 0 if not bound, - /// -1 if bound, and real date\time stamp - /// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) - /// O.W. date/time stamp of DLL bound to (Old BIND) - pub time_date_stamp: U32Bytes, - /// -1 if no forwarders - pub forwarder_chain: U32Bytes, - pub name: U32Bytes, - /// RVA to IAT (if bound this IAT has actual addresses) - pub first_thunk: U32Bytes, -} - -impl ImageImportDescriptor { - /// Tell whether this import descriptor is the null descriptor - /// (used to mark the end of the iterator array in a PE) - pub fn is_null(&self) -> bool { - self.original_first_thunk.get(LE) == 0 - && self.time_date_stamp.get(LE) == 0 - && self.forwarder_chain.get(LE) == 0 - && self.name.get(LE) == 0 - && self.first_thunk.get(LE) == 0 - } -} - -// -// New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ] -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageBoundImportDescriptor { - pub time_date_stamp: U32, - pub offset_module_name: U16, - pub number_of_module_forwarder_refs: U16, - // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageBoundForwarderRef { - pub time_date_stamp: U32, - pub offset_module_name: U16, - pub reserved: U16, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDelayloadDescriptor { - pub attributes: U32, - - /// RVA to the name of the target library (NULL-terminate ASCII string) - pub dll_name_rva: U32, - /// RVA to the HMODULE caching location (PHMODULE) - pub module_handle_rva: U32, - /// RVA to the start of the IAT (PIMAGE_THUNK_DATA) - pub import_address_table_rva: U32, - /// RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData) - pub import_name_table_rva: U32, - /// RVA to an optional bound IAT - pub bound_import_address_table_rva: U32, - /// RVA to an optional unload info table - pub unload_information_table_rva: U32, - /// 0 if not bound, otherwise, date/time of the target DLL - pub time_date_stamp: U32, -} - -impl ImageDelayloadDescriptor { - /// Tell whether this delay-load import descriptor is the null descriptor - /// (used to mark the end of the iterator array in a PE) - pub fn is_null(&self) -> bool { - self.attributes.get(LE) == 0 - && self.dll_name_rva.get(LE) == 0 - && self.module_handle_rva.get(LE) == 0 - && self.import_address_table_rva.get(LE) == 0 - && self.import_name_table_rva.get(LE) == 0 - && self.bound_import_address_table_rva.get(LE) == 0 - && self.unload_information_table_rva.get(LE) == 0 - && self.time_date_stamp.get(LE) == 0 - } -} - -/// Delay load version 2 flag for `ImageDelayloadDescriptor::attributes`. -pub const IMAGE_DELAYLOAD_RVA_BASED: u32 = 0x8000_0000; - -// -// Resource Format. -// - -// -// Resource directory consists of two counts, following by a variable length -// array of directory entries. The first count is the number of entries at -// beginning of the array that have actual names associated with each entry. -// The entries are in ascending order, case insensitive strings. The second -// count is the number of entries that immediately follow the named entries. -// This second count identifies the number of entries that have 16-bit integer -// Ids as their name. These entries are also sorted in ascending order. -// -// This structure allows fast lookup by either name or number, but for any -// given resource entry only one form of lookup is supported, not both. -// This is consistent with the syntax of the .RC file and the .RES file. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageResourceDirectory { - pub characteristics: U32, - pub time_date_stamp: U32, - pub major_version: U16, - pub minor_version: U16, - pub number_of_named_entries: U16, - pub number_of_id_entries: U16, -} - -pub const IMAGE_RESOURCE_NAME_IS_STRING: u32 = 0x8000_0000; -pub const IMAGE_RESOURCE_DATA_IS_DIRECTORY: u32 = 0x8000_0000; -// -// Each directory contains the 32-bit Name of the entry and an offset, -// relative to the beginning of the resource directory of the data associated -// with this directory entry. If the name of the entry is an actual text -// string instead of an integer Id, then the high order bit of the name field -// is set to one and the low order 31-bits are an offset, relative to the -// beginning of the resource directory of the string, which is of type -// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the -// low-order 16-bits are the integer Id that identify this resource directory -// entry. If the directory entry is yet another resource directory (i.e. a -// subdirectory), then the high order bit of the offset field will be -// set to indicate this. Otherwise the high bit is clear and the offset -// field points to a resource data entry. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageResourceDirectoryEntry { - pub name_or_id: U32, - pub offset_to_data_or_directory: U32, -} - -// -// For resource directory entries that have actual string names, the Name -// field of the directory entry points to an object of the following type. -// All of these string objects are stored together after the last resource -// directory entry and before the first resource data object. This minimizes -// the impact of these variable length objects on the alignment of the fixed -// size directory entry objects. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageResourceDirectoryString { - pub length: U16, - //pub name_string: [i8; 1], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageResourceDirStringU { - pub length: U16, - //pub name_string: [U16; 1], -} - -// -// Each resource data entry describes a leaf node in the resource directory -// tree. It contains an offset, relative to the beginning of the resource -// directory of the data for the resource, a size field that gives the number -// of bytes of data at that offset, a CodePage that should be used when -// decoding code point values within the resource data. Typically for new -// applications the code page would be the unicode code page. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageResourceDataEntry { - /// RVA of the data. - pub offset_to_data: U32, - pub size: U32, - pub code_page: U32, - pub reserved: U32, -} - -// Resource type: https://docs.microsoft.com/en-us/windows/win32/menurc/resource-types - -/// ID for: Hardware-dependent cursor resource. -pub const RT_CURSOR: u16 = 1; -/// ID for: Bitmap resource. -pub const RT_BITMAP: u16 = 2; -/// ID for: Hardware-dependent icon resource. -pub const RT_ICON: u16 = 3; -/// ID for: Menu resource. -pub const RT_MENU: u16 = 4; -/// ID for: Dialog box. -pub const RT_DIALOG: u16 = 5; -/// ID for: String-table entry. -pub const RT_STRING: u16 = 6; -/// ID for: Font directory resource. -pub const RT_FONTDIR: u16 = 7; -/// ID for: Font resource. -pub const RT_FONT: u16 = 8; -/// ID for: Accelerator table. -pub const RT_ACCELERATOR: u16 = 9; -/// ID for: Application-defined resource (raw data). -pub const RT_RCDATA: u16 = 10; -/// ID for: Message-table entry. -pub const RT_MESSAGETABLE: u16 = 11; -/// ID for: Hardware-independent cursor resource. -pub const RT_GROUP_CURSOR: u16 = 12; -/// ID for: Hardware-independent icon resource. -pub const RT_GROUP_ICON: u16 = 14; -/// ID for: Version resource. -pub const RT_VERSION: u16 = 16; -/// ID for: Allows a resource editing tool to associate a string with an .rc file. -pub const RT_DLGINCLUDE: u16 = 17; -/// ID for: Plug and Play resource. -pub const RT_PLUGPLAY: u16 = 19; -/// ID for: VXD. -pub const RT_VXD: u16 = 20; -/// ID for: Animated cursor. -pub const RT_ANICURSOR: u16 = 21; -/// ID for: Animated icon. -pub const RT_ANIICON: u16 = 22; -/// ID for: HTML resource. -pub const RT_HTML: u16 = 23; -/// ID for: Side-by-Side Assembly Manifest. -pub const RT_MANIFEST: u16 = 24; - -// -// Code Integrity in loadconfig (CI) -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageLoadConfigCodeIntegrity { - /// Flags to indicate if CI information is available, etc. - pub flags: U16, - /// 0xFFFF means not available - pub catalog: U16, - pub catalog_offset: U32, - /// Additional bitmask to be defined later - pub reserved: U32, -} - -// -// Dynamic value relocation table in loadconfig -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDynamicRelocationTable { - pub version: U32, - pub size: U32, - // DynamicRelocations: [ImageDynamicRelocation; 0], -} - -// -// Dynamic value relocation entries following IMAGE_DYNAMIC_RELOCATION_TABLE -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDynamicRelocation32 { - pub symbol: U32, - pub base_reloc_size: U32, - // BaseRelocations: [ImageBaseRelocation; 0], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDynamicRelocation64 { - pub symbol: U64, - pub base_reloc_size: U32, - // BaseRelocations: [ImageBaseRelocation; 0], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDynamicRelocation32V2 { - pub header_size: U32, - pub fixup_info_size: U32, - pub symbol: U32, - pub symbol_group: U32, - pub flags: U32, - // ... variable length header fields - // pub fixup_info: [u8; fixup_info_size] -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDynamicRelocation64V2 { - pub header_size: U32, - pub fixup_info_size: U32, - pub symbol: U64, - pub symbol_group: U32, - pub flags: U32, - // ... variable length header fields - // pub fixup_info[u8; fixup_info_size] -} - -// -// Defined symbolic dynamic relocation entries. -// - -pub const IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE: u32 = 0x0000_0001; -pub const IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE: u32 = 0x0000_0002; -pub const IMAGE_DYNAMIC_RELOCATION_GUARD_IMPORT_CONTROL_TRANSFER: u32 = 0x0000_0003; -pub const IMAGE_DYNAMIC_RELOCATION_GUARD_INDIR_CONTROL_TRANSFER: u32 = 0x0000_0004; -pub const IMAGE_DYNAMIC_RELOCATION_GUARD_SWITCHTABLE_BRANCH: u32 = 0x0000_0005; - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImagePrologueDynamicRelocationHeader { - pub prologue_byte_count: u8, - // pub prologue_bytes: [u8; prologue_byte_count], -} - -// This struct has alignment 1. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageEpilogueDynamicRelocationHeader { - pub epilogue_count: U32Bytes, - pub epilogue_byte_count: u8, - pub branch_descriptor_element_size: u8, - pub branch_descriptor_count: U16Bytes, - // pub branch_descriptors[...], - // pub branch_descriptor_bit_map[...], -} - -/* -// TODO? bitfields -// TODO: unaligned? -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageImportControlTransferDynamicRelocation { - DWORD PageRelativeOffset : 12; - DWORD IndirectCall : 1; - DWORD IATIndex : 19; -} - -// TODO: unaligned? -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageIndirControlTransferDynamicRelocation { - WORD PageRelativeOffset : 12; - WORD IndirectCall : 1; - WORD RexWPrefix : 1; - WORD CfgCheck : 1; - WORD Reserved : 1; -} - -// TODO: unaligned? -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSwitchtableBranchDynamicRelocation { - WORD PageRelativeOffset : 12; - WORD RegisterNumber : 4; -} -*/ - -// -// Load Configuration Directory Entry -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageLoadConfigDirectory32 { - pub size: U32, - pub time_date_stamp: U32, - pub major_version: U16, - pub minor_version: U16, - pub global_flags_clear: U32, - pub global_flags_set: U32, - pub critical_section_default_timeout: U32, - pub de_commit_free_block_threshold: U32, - pub de_commit_total_free_threshold: U32, - /// VA - pub lock_prefix_table: U32, - pub maximum_allocation_size: U32, - pub virtual_memory_threshold: U32, - pub process_heap_flags: U32, - pub process_affinity_mask: U32, - pub csd_version: U16, - pub dependent_load_flags: U16, - /// VA - pub edit_list: U32, - /// VA - pub security_cookie: U32, - /// VA - pub sehandler_table: U32, - pub sehandler_count: U32, - /// VA - pub guard_cf_check_function_pointer: U32, - /// VA - pub guard_cf_dispatch_function_pointer: U32, - /// VA - pub guard_cf_function_table: U32, - pub guard_cf_function_count: U32, - pub guard_flags: U32, - pub code_integrity: ImageLoadConfigCodeIntegrity, - /// VA - pub guard_address_taken_iat_entry_table: U32, - pub guard_address_taken_iat_entry_count: U32, - /// VA - pub guard_long_jump_target_table: U32, - pub guard_long_jump_target_count: U32, - /// VA - pub dynamic_value_reloc_table: U32, - pub chpe_metadata_pointer: U32, - /// VA - pub guard_rf_failure_routine: U32, - /// VA - pub guard_rf_failure_routine_function_pointer: U32, - pub dynamic_value_reloc_table_offset: U32, - pub dynamic_value_reloc_table_section: U16, - pub reserved2: U16, - /// VA - pub guard_rf_verify_stack_pointer_function_pointer: U32, - pub hot_patch_table_offset: U32, - pub reserved3: U32, - /// VA - pub enclave_configuration_pointer: U32, - /// VA - pub volatile_metadata_pointer: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageLoadConfigDirectory64 { - pub size: U32, - pub time_date_stamp: U32, - pub major_version: U16, - pub minor_version: U16, - pub global_flags_clear: U32, - pub global_flags_set: U32, - pub critical_section_default_timeout: U32, - pub de_commit_free_block_threshold: U64, - pub de_commit_total_free_threshold: U64, - /// VA - pub lock_prefix_table: U64, - pub maximum_allocation_size: U64, - pub virtual_memory_threshold: U64, - pub process_affinity_mask: U64, - pub process_heap_flags: U32, - pub csd_version: U16, - pub dependent_load_flags: U16, - /// VA - pub edit_list: U64, - /// VA - pub security_cookie: U64, - /// VA - pub sehandler_table: U64, - pub sehandler_count: U64, - /// VA - pub guard_cf_check_function_pointer: U64, - /// VA - pub guard_cf_dispatch_function_pointer: U64, - /// VA - pub guard_cf_function_table: U64, - pub guard_cf_function_count: U64, - pub guard_flags: U32, - pub code_integrity: ImageLoadConfigCodeIntegrity, - /// VA - pub guard_address_taken_iat_entry_table: U64, - pub guard_address_taken_iat_entry_count: U64, - /// VA - pub guard_long_jump_target_table: U64, - pub guard_long_jump_target_count: U64, - /// VA - pub dynamic_value_reloc_table: U64, - /// VA - pub chpe_metadata_pointer: U64, - /// VA - pub guard_rf_failure_routine: U64, - /// VA - pub guard_rf_failure_routine_function_pointer: U64, - pub dynamic_value_reloc_table_offset: U32, - pub dynamic_value_reloc_table_section: U16, - pub reserved2: U16, - /// VA - pub guard_rf_verify_stack_pointer_function_pointer: U64, - pub hot_patch_table_offset: U32, - pub reserved3: U32, - /// VA - pub enclave_configuration_pointer: U64, - /// VA - pub volatile_metadata_pointer: U64, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageHotPatchInfo { - pub version: U32, - pub size: U32, - pub sequence_number: U32, - pub base_image_list: U32, - pub base_image_count: U32, - /// Version 2 and later - pub buffer_offset: U32, - /// Version 3 and later - pub extra_patch_size: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageHotPatchBase { - pub sequence_number: U32, - pub flags: U32, - pub original_time_date_stamp: U32, - pub original_check_sum: U32, - pub code_integrity_info: U32, - pub code_integrity_size: U32, - pub patch_table: U32, - /// Version 2 and later - pub buffer_offset: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageHotPatchHashes { - pub sha256: [u8; 32], - pub sha1: [u8; 20], -} - -pub const IMAGE_HOT_PATCH_BASE_OBLIGATORY: u32 = 0x0000_0001; -pub const IMAGE_HOT_PATCH_BASE_CAN_ROLL_BACK: u32 = 0x0000_0002; - -pub const IMAGE_HOT_PATCH_CHUNK_INVERSE: u32 = 0x8000_0000; -pub const IMAGE_HOT_PATCH_CHUNK_OBLIGATORY: u32 = 0x4000_0000; -pub const IMAGE_HOT_PATCH_CHUNK_RESERVED: u32 = 0x3FF0_3000; -pub const IMAGE_HOT_PATCH_CHUNK_TYPE: u32 = 0x000F_C000; -pub const IMAGE_HOT_PATCH_CHUNK_SOURCE_RVA: u32 = 0x0000_8000; -pub const IMAGE_HOT_PATCH_CHUNK_TARGET_RVA: u32 = 0x0000_4000; -pub const IMAGE_HOT_PATCH_CHUNK_SIZE: u32 = 0x0000_0FFF; - -pub const IMAGE_HOT_PATCH_NONE: u32 = 0x0000_0000; -pub const IMAGE_HOT_PATCH_FUNCTION: u32 = 0x0001_C000; -pub const IMAGE_HOT_PATCH_ABSOLUTE: u32 = 0x0002_C000; -pub const IMAGE_HOT_PATCH_REL32: u32 = 0x0003_C000; -pub const IMAGE_HOT_PATCH_CALL_TARGET: u32 = 0x0004_4000; -pub const IMAGE_HOT_PATCH_INDIRECT: u32 = 0x0005_C000; -pub const IMAGE_HOT_PATCH_NO_CALL_TARGET: u32 = 0x0006_4000; -pub const IMAGE_HOT_PATCH_DYNAMIC_VALUE: u32 = 0x0007_8000; - -/// Module performs control flow integrity checks using system-supplied support -pub const IMAGE_GUARD_CF_INSTRUMENTED: u32 = 0x0000_0100; -/// Module performs control flow and write integrity checks -pub const IMAGE_GUARD_CFW_INSTRUMENTED: u32 = 0x0000_0200; -/// Module contains valid control flow target metadata -pub const IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT: u32 = 0x0000_0400; -/// Module does not make use of the /GS security cookie -pub const IMAGE_GUARD_SECURITY_COOKIE_UNUSED: u32 = 0x0000_0800; -/// Module supports read only delay load IAT -pub const IMAGE_GUARD_PROTECT_DELAYLOAD_IAT: u32 = 0x0000_1000; -/// Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected -pub const IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION: u32 = 0x0000_2000; -/// Module contains suppressed export information. -/// -/// This also infers that the address taken taken IAT table is also present in the load config. -pub const IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT: u32 = 0x0000_4000; -/// Module enables suppression of exports -pub const IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION: u32 = 0x0000_8000; -/// Module contains longjmp target information -pub const IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT: u32 = 0x0001_0000; -/// Module contains return flow instrumentation and metadata -pub const IMAGE_GUARD_RF_INSTRUMENTED: u32 = 0x0002_0000; -/// Module requests that the OS enable return flow protection -pub const IMAGE_GUARD_RF_ENABLE: u32 = 0x0004_0000; -/// Module requests that the OS enable return flow protection in strict mode -pub const IMAGE_GUARD_RF_STRICT: u32 = 0x0008_0000; -/// Module was built with retpoline support -pub const IMAGE_GUARD_RETPOLINE_PRESENT: u32 = 0x0010_0000; - -/// Stride of Guard CF function table encoded in these bits (additional count of bytes per element) -pub const IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK: u32 = 0xF000_0000; -/// Shift to right-justify Guard CF function table stride -pub const IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT: u32 = 28; - -// -// GFIDS table entry flags. -// - -/// The containing GFID entry is suppressed -pub const IMAGE_GUARD_FLAG_FID_SUPPRESSED: u16 = 0x01; -/// The containing GFID entry is export suppressed -pub const IMAGE_GUARD_FLAG_EXPORT_SUPPRESSED: u16 = 0x02; - -// -// WIN CE Exception table format -// - -// -// Function table entry format. Function table is pointed to by the -// IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry. -// - -/* -// TODO? bitfields -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageCeRuntimeFunctionEntry { - pub func_start: U32, - DWORD PrologLen : 8; - DWORD FuncLen : 22; - DWORD ThirtyTwoBit : 1; - DWORD ExceptionFlag : 1; -} -*/ - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageArmRuntimeFunctionEntry { - pub begin_address: U32, - pub unwind_data: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageArm64RuntimeFunctionEntry { - pub begin_address: U32, - pub unwind_data: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAlpha64RuntimeFunctionEntry { - pub begin_address: U64, - pub end_address: U64, - pub exception_handler: U64, - pub handler_data: U64, - pub prolog_end_address: U64, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageAlphaRuntimeFunctionEntry { - pub begin_address: U32, - pub end_address: U32, - pub exception_handler: U32, - pub handler_data: U32, - pub prolog_end_address: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageRuntimeFunctionEntry { - pub begin_address: U32, - pub end_address: U32, - pub unwind_info_address_or_data: U32, -} - -// -// Software enclave information -// - -pub const IMAGE_ENCLAVE_LONG_ID_LENGTH: usize = 32; -pub const IMAGE_ENCLAVE_SHORT_ID_LENGTH: usize = 16; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageEnclaveConfig32 { - pub size: U32, - pub minimum_required_config_size: U32, - pub policy_flags: U32, - pub number_of_imports: U32, - pub import_list: U32, - pub import_entry_size: U32, - pub family_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub image_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub image_version: U32, - pub security_version: U32, - pub enclave_size: U32, - pub number_of_threads: U32, - pub enclave_flags: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageEnclaveConfig64 { - pub size: U32, - pub minimum_required_config_size: U32, - pub policy_flags: U32, - pub number_of_imports: U32, - pub import_list: U32, - pub import_entry_size: U32, - pub family_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub image_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub image_version: U32, - pub security_version: U32, - pub enclave_size: U64, - pub number_of_threads: U32, - pub enclave_flags: U32, -} - -//pub const IMAGE_ENCLAVE_MINIMUM_CONFIG_SIZE: usize = FIELD_OFFSET(IMAGE_ENCLAVE_CONFIG, EnclaveFlags); - -pub const IMAGE_ENCLAVE_POLICY_DEBUGGABLE: u32 = 0x0000_0001; - -pub const IMAGE_ENCLAVE_FLAG_PRIMARY_IMAGE: u32 = 0x0000_0001; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageEnclaveImport { - pub match_type: U32, - pub minimum_security_version: U32, - pub unique_or_author_id: [u8; IMAGE_ENCLAVE_LONG_ID_LENGTH], - pub family_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub image_id: [u8; IMAGE_ENCLAVE_SHORT_ID_LENGTH], - pub import_name: U32, - pub reserved: U32, -} - -pub const IMAGE_ENCLAVE_IMPORT_MATCH_NONE: u32 = 0x0000_0000; -pub const IMAGE_ENCLAVE_IMPORT_MATCH_UNIQUE_ID: u32 = 0x0000_0001; -pub const IMAGE_ENCLAVE_IMPORT_MATCH_AUTHOR_ID: u32 = 0x0000_0002; -pub const IMAGE_ENCLAVE_IMPORT_MATCH_FAMILY_ID: u32 = 0x0000_0003; -pub const IMAGE_ENCLAVE_IMPORT_MATCH_IMAGE_ID: u32 = 0x0000_0004; - -// -// Debug Format -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDebugDirectory { - pub characteristics: U32, - pub time_date_stamp: U32, - pub major_version: U16, - pub minor_version: U16, - pub typ: U32, - pub size_of_data: U32, - pub address_of_raw_data: U32, - pub pointer_to_raw_data: U32, -} - -pub const IMAGE_DEBUG_TYPE_UNKNOWN: u32 = 0; -pub const IMAGE_DEBUG_TYPE_COFF: u32 = 1; -pub const IMAGE_DEBUG_TYPE_CODEVIEW: u32 = 2; -pub const IMAGE_DEBUG_TYPE_FPO: u32 = 3; -pub const IMAGE_DEBUG_TYPE_MISC: u32 = 4; -pub const IMAGE_DEBUG_TYPE_EXCEPTION: u32 = 5; -pub const IMAGE_DEBUG_TYPE_FIXUP: u32 = 6; -pub const IMAGE_DEBUG_TYPE_OMAP_TO_SRC: u32 = 7; -pub const IMAGE_DEBUG_TYPE_OMAP_FROM_SRC: u32 = 8; -pub const IMAGE_DEBUG_TYPE_BORLAND: u32 = 9; -pub const IMAGE_DEBUG_TYPE_RESERVED10: u32 = 10; -pub const IMAGE_DEBUG_TYPE_CLSID: u32 = 11; -pub const IMAGE_DEBUG_TYPE_VC_FEATURE: u32 = 12; -pub const IMAGE_DEBUG_TYPE_POGO: u32 = 13; -pub const IMAGE_DEBUG_TYPE_ILTCG: u32 = 14; -pub const IMAGE_DEBUG_TYPE_MPX: u32 = 15; -pub const IMAGE_DEBUG_TYPE_REPRO: u32 = 16; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageCoffSymbolsHeader { - pub number_of_symbols: U32, - pub lva_to_first_symbol: U32, - pub number_of_linenumbers: U32, - pub lva_to_first_linenumber: U32, - pub rva_to_first_byte_of_code: U32, - pub rva_to_last_byte_of_code: U32, - pub rva_to_first_byte_of_data: U32, - pub rva_to_last_byte_of_data: U32, -} - -pub const FRAME_FPO: u16 = 0; -pub const FRAME_TRAP: u16 = 1; -pub const FRAME_TSS: u16 = 2; -pub const FRAME_NONFPO: u16 = 3; - -/* -// TODO? bitfields -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FpoData { -/// offset 1st byte of function code - pub ul_off_start: U32, -/// # bytes in function - pub cb_proc_size: U32, -/// # bytes in locals/4 - pub cdw_locals: U32, -/// # bytes in params/4 - pub cdw_params: U16, -/// # bytes in prolog - WORD cbProlog : 8; -/// # regs saved - WORD cbRegs : 3; -/// TRUE if SEH in func - WORD fHasSEH : 1; -/// TRUE if EBP has been allocated - WORD fUseBP : 1; -/// reserved for future use - WORD reserved : 1; -/// frame type - WORD cbFrame : 2; -} -pub const SIZEOF_RFPO_DATA: usize = 16; -*/ - -pub const IMAGE_DEBUG_MISC_EXENAME: u16 = 1; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageDebugMisc { - /// type of misc data, see defines - pub data_type: U32, - /// total length of record, rounded to four byte multiple. - pub length: U32, - /// TRUE if data is unicode string - pub unicode: u8, - pub reserved: [u8; 3], - // Actual data - //pub data: [u8; 1], -} - -// -// Function table extracted from MIPS/ALPHA/IA64 images. Does not contain -// information needed only for runtime support. Just those fields for -// each entry needed by a debugger. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageFunctionEntry { - pub starting_address: U32, - pub ending_address: U32, - pub end_of_prologue: U32, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageFunctionEntry64 { - pub starting_address: U64, - pub ending_address: U64, - pub end_of_prologue_or_unwind_info_address: U64, -} - -// -// Debugging information can be stripped from an image file and placed -// in a separate .DBG file, whose file name part is the same as the -// image file name part (e.g. symbols for CMD.EXE could be stripped -// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED -// flag in the Characteristics field of the file header. The beginning of -// the .DBG file contains the following structure which captures certain -// information from the image file. This allows a debug to proceed even if -// the original image file is not accessible. This header is followed by -// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more -// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in -// the image file contain file offsets relative to the beginning of the -// .DBG file. -// -// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure -// is left in the image file, but not mapped. This allows a debugger to -// compute the name of the .DBG file, from the name of the image in the -// IMAGE_DEBUG_MISC structure. -// - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageSeparateDebugHeader { - pub signature: U16, - pub flags: U16, - pub machine: U16, - pub characteristics: U16, - pub time_date_stamp: U32, - pub check_sum: U32, - pub image_base: U32, - pub size_of_image: U32, - pub number_of_sections: U32, - pub exported_names_size: U32, - pub debug_directory_size: U32, - pub section_alignment: U32, - pub reserved: [U32; 2], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct NonPagedDebugInfo { - pub signature: U16, - pub flags: U16, - pub size: U32, - pub machine: U16, - pub characteristics: U16, - pub time_date_stamp: U32, - pub check_sum: U32, - pub size_of_image: U32, - pub image_base: U64, - //debug_directory_size - //ImageDebugDirectory -} - -pub const IMAGE_SEPARATE_DEBUG_SIGNATURE: u16 = 0x4944; -pub const NON_PAGED_DEBUG_SIGNATURE: u16 = 0x494E; - -pub const IMAGE_SEPARATE_DEBUG_FLAGS_MASK: u16 = 0x8000; -/// when DBG was updated, the old checksum didn't match. -pub const IMAGE_SEPARATE_DEBUG_MISMATCH: u16 = 0x8000; - -// -// The .arch section is made up of headers, each describing an amask position/value -// pointing to an array of IMAGE_ARCHITECTURE_ENTRY's. Each "array" (both the header -// and entry arrays) are terminiated by a quadword of 0xffffffffL. -// -// NOTE: There may be quadwords of 0 sprinkled around and must be skipped. -// - -/* -// TODO? bitfields -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageArchitectureHeader { - /// 1 -> code section depends on mask bit - /// 0 -> new instruction depends on mask bit - unsigned int AmaskValue: 1; - /// MBZ - int :7; - /// Amask bit in question for this fixup - unsigned int AmaskShift: 8; - /// MBZ - int :16; - /// RVA into .arch section to array of ARCHITECTURE_ENTRY's - pub first_entry_rva: U32, -} -*/ - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageArchitectureEntry { - /// RVA of instruction to fixup - pub fixup_inst_rva: U32, - /// fixup instruction (see alphaops.h) - pub new_inst: U32, -} - -// The following structure defines the new import object. Note the values of the first two fields, -// which must be set as stated in order to differentiate old and new import members. -// Following this structure, the linker emits two null-terminated strings used to recreate the -// import at the time of use. The first string is the import's name, the second is the dll's name. - -pub const IMPORT_OBJECT_HDR_SIG2: u16 = 0xffff; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImportObjectHeader { - /// Must be IMAGE_FILE_MACHINE_UNKNOWN - pub sig1: U16, - /// Must be IMPORT_OBJECT_HDR_SIG2. - pub sig2: U16, - pub version: U16, - pub machine: U16, - /// Time/date stamp - pub time_date_stamp: U32, - /// particularly useful for incremental links - pub size_of_data: U32, - - /// if grf & IMPORT_OBJECT_ORDINAL - pub ordinal_or_hint: U16, - - // WORD Type : 2; - // WORD NameType : 3; - // WORD Reserved : 11; - pub name_type: U16, -} - -pub const IMPORT_OBJECT_TYPE_MASK: u16 = 0b11; -pub const IMPORT_OBJECT_TYPE_SHIFT: u16 = 0; -pub const IMPORT_OBJECT_CODE: u16 = 0; -pub const IMPORT_OBJECT_DATA: u16 = 1; -pub const IMPORT_OBJECT_CONST: u16 = 2; - -pub const IMPORT_OBJECT_NAME_MASK: u16 = 0b111; -pub const IMPORT_OBJECT_NAME_SHIFT: u16 = 2; -/// Import by ordinal -pub const IMPORT_OBJECT_ORDINAL: u16 = 0; -/// Import name == public symbol name. -pub const IMPORT_OBJECT_NAME: u16 = 1; -/// Import name == public symbol name skipping leading ?, @, or optionally _. -pub const IMPORT_OBJECT_NAME_NO_PREFIX: u16 = 2; -/// Import name == public symbol name skipping leading ?, @, or optionally _ and truncating at first @. -pub const IMPORT_OBJECT_NAME_UNDECORATE: u16 = 3; -/// Import name == a name is explicitly provided after the DLL name. -pub const IMPORT_OBJECT_NAME_EXPORTAS: u16 = 4; - -// COM+ Header entry point flags. -pub const COMIMAGE_FLAGS_ILONLY: u32 = 0x0000_0001; -pub const COMIMAGE_FLAGS_32BITREQUIRED: u32 = 0x0000_0002; -pub const COMIMAGE_FLAGS_IL_LIBRARY: u32 = 0x0000_0004; -pub const COMIMAGE_FLAGS_STRONGNAMESIGNED: u32 = 0x0000_0008; -pub const COMIMAGE_FLAGS_NATIVE_ENTRYPOINT: u32 = 0x0000_0010; -pub const COMIMAGE_FLAGS_TRACKDEBUGDATA: u32 = 0x0001_0000; -pub const COMIMAGE_FLAGS_32BITPREFERRED: u32 = 0x0002_0000; - -// Version flags for image. -pub const COR_VERSION_MAJOR_V2: u16 = 2; -pub const COR_VERSION_MAJOR: u16 = COR_VERSION_MAJOR_V2; -pub const COR_VERSION_MINOR: u16 = 5; -pub const COR_DELETED_NAME_LENGTH: usize = 8; -pub const COR_VTABLEGAP_NAME_LENGTH: usize = 8; - -// Maximum size of a NativeType descriptor. -pub const NATIVE_TYPE_MAX_CB: u16 = 1; -pub const COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE: u16 = 0xFF; - -// Consts for the MIH FLAGS -pub const IMAGE_COR_MIH_METHODRVA: u16 = 0x01; -pub const IMAGE_COR_MIH_EHRVA: u16 = 0x02; -pub const IMAGE_COR_MIH_BASICBLOCK: u16 = 0x08; - -// V-table constants -/// V-table slots are 32-bits in size. -pub const COR_VTABLE_32BIT: u16 = 0x01; -/// V-table slots are 64-bits in size. -pub const COR_VTABLE_64BIT: u16 = 0x02; -/// If set, transition from unmanaged. -pub const COR_VTABLE_FROM_UNMANAGED: u16 = 0x04; -/// If set, transition from unmanaged with keeping the current appdomain. -pub const COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN: u16 = 0x08; -/// Call most derived method described by -pub const COR_VTABLE_CALL_MOST_DERIVED: u16 = 0x10; - -// EATJ constants -/// Size of a jump thunk reserved range. -pub const IMAGE_COR_EATJ_THUNK_SIZE: usize = 32; - -// Max name lengths -pub const MAX_CLASS_NAME: usize = 1024; -pub const MAX_PACKAGE_NAME: usize = 1024; - -// CLR 2.0 header structure. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ImageCor20Header { - // Header versioning - pub cb: U32, - pub major_runtime_version: U16, - pub minor_runtime_version: U16, - - // Symbol table and startup information - pub meta_data: ImageDataDirectory, - pub flags: U32, - - // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. - // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint. - pub entry_point_token_or_rva: U32, - - // Binding information - pub resources: ImageDataDirectory, - pub strong_name_signature: ImageDataDirectory, - - // Regular fixup and binding information - pub code_manager_table: ImageDataDirectory, - pub vtable_fixups: ImageDataDirectory, - pub export_address_table_jumps: ImageDataDirectory, - - // Precompiled image info (internal use only - set to zero) - pub managed_native_header: ImageDataDirectory, -} - -unsafe_impl_pod!( - ImageDosHeader, - ImageOs2Header, - ImageVxdHeader, - ImageFileHeader, - ImageDataDirectory, - ImageOptionalHeader32, - ImageRomOptionalHeader, - ImageOptionalHeader64, - ImageNtHeaders64, - ImageNtHeaders32, - ImageRomHeaders, - Guid, - AnonObjectHeader, - AnonObjectHeaderV2, - AnonObjectHeaderBigobj, - ImageSectionHeader, - ImageSymbol, - ImageSymbolBytes, - ImageSymbolEx, - ImageSymbolExBytes, - ImageAuxSymbolTokenDef, - ImageAuxSymbolFunction, - ImageAuxSymbolFunctionBeginEnd, - ImageAuxSymbolWeak, - ImageAuxSymbolSection, - ImageAuxSymbolCrc, - ImageRelocation, - ImageLinenumber, - ImageBaseRelocation, - ImageArchiveMemberHeader, - ImageExportDirectory, - ImageImportByName, - ImageThunkData64, - ImageThunkData32, - ImageTlsDirectory64, - ImageTlsDirectory32, - ImageImportDescriptor, - ImageBoundImportDescriptor, - ImageBoundForwarderRef, - ImageDelayloadDescriptor, - ImageResourceDirectory, - ImageResourceDirectoryEntry, - ImageResourceDirectoryString, - ImageResourceDirStringU, - ImageResourceDataEntry, - ImageLoadConfigCodeIntegrity, - ImageDynamicRelocationTable, - ImageDynamicRelocation32, - ImageDynamicRelocation64, - ImageDynamicRelocation32V2, - ImageDynamicRelocation64V2, - ImagePrologueDynamicRelocationHeader, - ImageEpilogueDynamicRelocationHeader, - //ImageImportControlTransferDynamicRelocation, - //ImageIndirControlTransferDynamicRelocation, - //ImageSwitchtableBranchDynamicRelocation, - ImageLoadConfigDirectory32, - ImageLoadConfigDirectory64, - ImageHotPatchInfo, - ImageHotPatchBase, - ImageHotPatchHashes, - //ImageCeRuntimeFunctionEntry, - ImageArmRuntimeFunctionEntry, - ImageArm64RuntimeFunctionEntry, - ImageAlpha64RuntimeFunctionEntry, - ImageAlphaRuntimeFunctionEntry, - ImageRuntimeFunctionEntry, - ImageEnclaveConfig32, - ImageEnclaveConfig64, - ImageEnclaveImport, - ImageDebugDirectory, - ImageCoffSymbolsHeader, - //FpoData, - ImageDebugMisc, - ImageFunctionEntry, - ImageFunctionEntry64, - ImageSeparateDebugHeader, - NonPagedDebugInfo, - //ImageArchitectureHeader, - ImageArchitectureEntry, - ImportObjectHeader, - ImageCor20Header, - MaskedRichHeaderEntry, -); diff --git a/vendor/object/src/pod.rs b/vendor/object/src/pod.rs deleted file mode 100644 index 8ee7816..0000000 --- a/vendor/object/src/pod.rs +++ /dev/null @@ -1,239 +0,0 @@ -//! Tools for converting file format structures to and from bytes. -//! -//! This module should be replaced once rust provides safe transmutes. - -// This module provides functions for both read and write features. -#![cfg_attr( - not(all(feature = "read_core", feature = "write_core")), - allow(dead_code) -)] - -use core::{mem, result, slice}; - -type Result = result::Result; - -/// A trait for types that can safely be converted from and to byte slices. -/// -/// # Safety -/// A type that is `Pod` must: -/// - be `#[repr(C)]` or `#[repr(transparent)]` -/// - have no invalid byte values -/// - have no padding -pub unsafe trait Pod: Copy + 'static {} - -/// Cast a byte slice to a `Pod` type. -/// -/// Returns the type and the tail of the slice. -#[inline] -pub fn from_bytes(data: &[u8]) -> Result<(&T, &[u8])> { - let size = mem::size_of::(); - let tail = data.get(size..).ok_or(())?; - let ptr = data.as_ptr(); - if (ptr as usize) % mem::align_of::() != 0 { - return Err(()); - } - // Safety: - // The alignment and size are checked by this function. - // The Pod trait ensures the type is valid to cast from bytes. - let val = unsafe { &*ptr.cast() }; - Ok((val, tail)) -} - -/// Cast a mutable byte slice to a `Pod` type. -/// -/// Returns the type and the tail of the slice. -#[inline] -pub fn from_bytes_mut(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> { - let size = mem::size_of::(); - if size > data.len() { - return Err(()); - } - let (data, tail) = data.split_at_mut(size); - let ptr = data.as_mut_ptr(); - if (ptr as usize) % mem::align_of::() != 0 { - return Err(()); - } - // Safety: - // The alignment and size are checked by this function. - // The Pod trait ensures the type is valid to cast from bytes. - let val = unsafe { &mut *ptr.cast() }; - Ok((val, tail)) -} - -/// Cast a byte slice to a slice of a `Pod` type. -/// -/// Returns the type slice and the tail of the byte slice. -#[inline] -pub fn slice_from_bytes(data: &[u8], count: usize) -> Result<(&[T], &[u8])> { - let size = count.checked_mul(mem::size_of::()).ok_or(())?; - let tail = data.get(size..).ok_or(())?; - let ptr = data.as_ptr(); - if (ptr as usize) % mem::align_of::() != 0 { - return Err(()); - } - // Safety: - // The alignment and size are checked by this function. - // The Pod trait ensures the type is valid to cast from bytes. - let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) }; - Ok((slice, tail)) -} - -/// Cast a mutable byte slice to a slice of a `Pod` type. -/// -/// Returns the type slice and the tail of the byte slice. -#[inline] -pub fn slice_from_bytes_mut( - data: &mut [u8], - count: usize, -) -> Result<(&mut [T], &mut [u8])> { - let size = count.checked_mul(mem::size_of::()).ok_or(())?; - if size > data.len() { - return Err(()); - } - let (data, tail) = data.split_at_mut(size); - let ptr = data.as_mut_ptr(); - if (ptr as usize) % mem::align_of::() != 0 { - return Err(()); - } - // Safety: - // The alignment and size are checked by this function. - // The Pod trait ensures the type is valid to cast from bytes. - let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), count) }; - Ok((slice, tail)) -} - -/// Cast a `Pod` type to a byte slice. -#[inline] -pub fn bytes_of(val: &T) -> &[u8] { - let size = mem::size_of::(); - // Safety: - // Any alignment is allowed. - // The size is determined in this function. - // The Pod trait ensures the type is valid to cast to bytes. - unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) } -} - -/// Cast a `Pod` type to a mutable byte slice. -#[inline] -pub fn bytes_of_mut(val: &mut T) -> &mut [u8] { - let size = mem::size_of::(); - // Safety: - // Any alignment is allowed. - // The size is determined in this function. - // The Pod trait ensures the type is valid to cast to bytes. - unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) } -} - -/// Cast a slice of a `Pod` type to a byte slice. -#[inline] -pub fn bytes_of_slice(val: &[T]) -> &[u8] { - let size = val.len().wrapping_mul(mem::size_of::()); - // Safety: - // Any alignment is allowed. - // The size is determined in this function. - // The Pod trait ensures the type is valid to cast to bytes. - unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) } -} - -/// Cast a slice of a `Pod` type to a mutable byte slice. -#[inline] -pub fn bytes_of_slice_mut(val: &mut [T]) -> &mut [u8] { - let size = val.len().wrapping_mul(mem::size_of::()); - // Safety: - // Any alignment is allowed. - // The size is determined in this function. - // The Pod trait ensures the type is valid to cast to bytes. - unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) } -} - -macro_rules! unsafe_impl_pod { - ($($struct_name:ident),+ $(,)?) => { - $( - unsafe impl Pod for $struct_name { } - )+ - } -} - -unsafe_impl_pod!(u8, u16, u32, u64); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn single() { - let x = u32::to_be(0x0123_4567); - let mut x_mut = x; - let bytes = bytes_of(&x); - let bytes_mut = bytes_of_mut(&mut x_mut); - assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]); - assert_eq!(bytes, bytes_mut); - - let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)]; - - let (y, tail) = from_bytes::(bytes).unwrap(); - let (y_mut, tail_mut) = from_bytes_mut::(bytes_mut).unwrap(); - assert_eq!(*y, x); - assert_eq!(y, y_mut); - assert_eq!(tail, &[]); - assert_eq!(tail, tail_mut); - - let (y, tail) = from_bytes::(bytes).unwrap(); - let (y_mut, tail_mut) = from_bytes_mut::(bytes_mut).unwrap(); - assert_eq!(*y, x16[0]); - assert_eq!(y, y_mut); - assert_eq!(tail, &bytes[2..]); - assert_eq!(tail, tail_mut); - - let (y, tail) = from_bytes::(&bytes[2..]).unwrap(); - let (y_mut, tail_mut) = from_bytes_mut::(&mut bytes_mut[2..]).unwrap(); - assert_eq!(*y, x16[1]); - assert_eq!(y, y_mut); - assert_eq!(tail, &[]); - assert_eq!(tail, tail_mut); - - assert_eq!(from_bytes::(&bytes[1..]), Err(())); - assert_eq!(from_bytes::(&bytes[3..]), Err(())); - assert_eq!(from_bytes::(&bytes[4..]), Err(())); - assert_eq!(from_bytes_mut::(&mut bytes_mut[1..]), Err(())); - assert_eq!(from_bytes_mut::(&mut bytes_mut[3..]), Err(())); - assert_eq!(from_bytes_mut::(&mut bytes_mut[4..]), Err(())); - } - - #[test] - fn slice() { - let x = [ - u16::to_be(0x0123), - u16::to_be(0x4567), - u16::to_be(0x89ab), - u16::to_be(0xcdef), - ]; - let mut x_mut = x; - - let bytes = bytes_of_slice(&x); - let bytes_mut = bytes_of_slice_mut(&mut x_mut); - assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]); - assert_eq!(bytes, bytes_mut); - - let (y, tail) = slice_from_bytes::(bytes, 4).unwrap(); - let (y_mut, tail_mut) = slice_from_bytes_mut::(bytes_mut, 4).unwrap(); - assert_eq!(y, x); - assert_eq!(y, y_mut); - assert_eq!(tail, &[]); - assert_eq!(tail, tail_mut); - - let (y, tail) = slice_from_bytes::(&bytes[2..], 2).unwrap(); - let (y_mut, tail_mut) = slice_from_bytes::(&mut bytes_mut[2..], 2).unwrap(); - assert_eq!(y, &x[1..3]); - assert_eq!(y, y_mut); - assert_eq!(tail, &bytes[6..]); - assert_eq!(tail, tail_mut); - - assert_eq!(slice_from_bytes::(bytes, 5), Err(())); - assert_eq!(slice_from_bytes::(&bytes[2..], 4), Err(())); - assert_eq!(slice_from_bytes::(&bytes[1..], 2), Err(())); - assert_eq!(slice_from_bytes_mut::(bytes_mut, 5), Err(())); - assert_eq!(slice_from_bytes_mut::(&mut bytes_mut[2..], 4), Err(())); - assert_eq!(slice_from_bytes_mut::(&mut bytes_mut[1..], 2), Err(())); - } -} diff --git a/vendor/object/src/read/any.rs b/vendor/object/src/read/any.rs deleted file mode 100644 index a14e56d..0000000 --- a/vendor/object/src/read/any.rs +++ /dev/null @@ -1,1328 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::marker::PhantomData; - -#[cfg(feature = "coff")] -use crate::read::coff; -#[cfg(feature = "elf")] -use crate::read::elf; -#[cfg(feature = "macho")] -use crate::read::macho; -#[cfg(feature = "pe")] -use crate::read::pe; -#[cfg(feature = "wasm")] -use crate::read::wasm; -#[cfg(feature = "xcoff")] -use crate::read::xcoff; -use crate::read::{ - self, Architecture, BinaryFormat, CodeView, ComdatKind, CompressedData, CompressedFileRange, - Error, Export, FileFlags, FileKind, Import, Object, ObjectComdat, ObjectKind, ObjectMap, - ObjectSection, ObjectSegment, ObjectSymbol, ObjectSymbolTable, ReadRef, Relocation, Result, - SectionFlags, SectionIndex, SectionKind, SegmentFlags, SymbolFlags, SymbolIndex, SymbolKind, - SymbolMap, SymbolMapName, SymbolScope, SymbolSection, -}; -#[allow(unused_imports)] -use crate::{AddressSize, Endian, Endianness, SubArchitecture}; - -/// Evaluate an expression on the contents of a file format enum. -/// -/// This is a hack to avoid virtual calls. -macro_rules! with_inner { - ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { - match $inner { - #[cfg(feature = "coff")] - $enum::Coff(ref $var) => $body, - #[cfg(feature = "coff")] - $enum::CoffBig(ref $var) => $body, - #[cfg(feature = "elf")] - $enum::Elf32(ref $var) => $body, - #[cfg(feature = "elf")] - $enum::Elf64(ref $var) => $body, - #[cfg(feature = "macho")] - $enum::MachO32(ref $var) => $body, - #[cfg(feature = "macho")] - $enum::MachO64(ref $var) => $body, - #[cfg(feature = "pe")] - $enum::Pe32(ref $var) => $body, - #[cfg(feature = "pe")] - $enum::Pe64(ref $var) => $body, - #[cfg(feature = "wasm")] - $enum::Wasm(ref $var) => $body, - #[cfg(feature = "xcoff")] - $enum::Xcoff32(ref $var) => $body, - #[cfg(feature = "xcoff")] - $enum::Xcoff64(ref $var) => $body, - } - }; -} - -macro_rules! with_inner_mut { - ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { - match $inner { - #[cfg(feature = "coff")] - $enum::Coff(ref mut $var) => $body, - #[cfg(feature = "coff")] - $enum::CoffBig(ref mut $var) => $body, - #[cfg(feature = "elf")] - $enum::Elf32(ref mut $var) => $body, - #[cfg(feature = "elf")] - $enum::Elf64(ref mut $var) => $body, - #[cfg(feature = "macho")] - $enum::MachO32(ref mut $var) => $body, - #[cfg(feature = "macho")] - $enum::MachO64(ref mut $var) => $body, - #[cfg(feature = "pe")] - $enum::Pe32(ref mut $var) => $body, - #[cfg(feature = "pe")] - $enum::Pe64(ref mut $var) => $body, - #[cfg(feature = "wasm")] - $enum::Wasm(ref mut $var) => $body, - #[cfg(feature = "xcoff")] - $enum::Xcoff32(ref mut $var) => $body, - #[cfg(feature = "xcoff")] - $enum::Xcoff64(ref mut $var) => $body, - } - }; -} - -/// Like `with_inner!`, but wraps the result in another enum. -macro_rules! map_inner { - ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { - match $inner { - #[cfg(feature = "coff")] - $from::Coff(ref $var) => $to::Coff($body), - #[cfg(feature = "coff")] - $from::CoffBig(ref $var) => $to::CoffBig($body), - #[cfg(feature = "elf")] - $from::Elf32(ref $var) => $to::Elf32($body), - #[cfg(feature = "elf")] - $from::Elf64(ref $var) => $to::Elf64($body), - #[cfg(feature = "macho")] - $from::MachO32(ref $var) => $to::MachO32($body), - #[cfg(feature = "macho")] - $from::MachO64(ref $var) => $to::MachO64($body), - #[cfg(feature = "pe")] - $from::Pe32(ref $var) => $to::Pe32($body), - #[cfg(feature = "pe")] - $from::Pe64(ref $var) => $to::Pe64($body), - #[cfg(feature = "wasm")] - $from::Wasm(ref $var) => $to::Wasm($body), - #[cfg(feature = "xcoff")] - $from::Xcoff32(ref $var) => $to::Xcoff32($body), - #[cfg(feature = "xcoff")] - $from::Xcoff64(ref $var) => $to::Xcoff64($body), - } - }; -} - -/// Like `map_inner!`, but the result is a Result or Option. -macro_rules! map_inner_option { - ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { - match $inner { - #[cfg(feature = "coff")] - $from::Coff(ref $var) => $body.map($to::Coff), - #[cfg(feature = "coff")] - $from::CoffBig(ref $var) => $body.map($to::CoffBig), - #[cfg(feature = "elf")] - $from::Elf32(ref $var) => $body.map($to::Elf32), - #[cfg(feature = "elf")] - $from::Elf64(ref $var) => $body.map($to::Elf64), - #[cfg(feature = "macho")] - $from::MachO32(ref $var) => $body.map($to::MachO32), - #[cfg(feature = "macho")] - $from::MachO64(ref $var) => $body.map($to::MachO64), - #[cfg(feature = "pe")] - $from::Pe32(ref $var) => $body.map($to::Pe32), - #[cfg(feature = "pe")] - $from::Pe64(ref $var) => $body.map($to::Pe64), - #[cfg(feature = "wasm")] - $from::Wasm(ref $var) => $body.map($to::Wasm), - #[cfg(feature = "xcoff")] - $from::Xcoff32(ref $var) => $body.map($to::Xcoff32), - #[cfg(feature = "xcoff")] - $from::Xcoff64(ref $var) => $body.map($to::Xcoff64), - } - }; -} - -macro_rules! map_inner_option_mut { - ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { - match $inner { - #[cfg(feature = "coff")] - $from::Coff(ref mut $var) => $body.map($to::Coff), - #[cfg(feature = "coff")] - $from::CoffBig(ref mut $var) => $body.map($to::CoffBig), - #[cfg(feature = "elf")] - $from::Elf32(ref mut $var) => $body.map($to::Elf32), - #[cfg(feature = "elf")] - $from::Elf64(ref mut $var) => $body.map($to::Elf64), - #[cfg(feature = "macho")] - $from::MachO32(ref mut $var) => $body.map($to::MachO32), - #[cfg(feature = "macho")] - $from::MachO64(ref mut $var) => $body.map($to::MachO64), - #[cfg(feature = "pe")] - $from::Pe32(ref mut $var) => $body.map($to::Pe32), - #[cfg(feature = "pe")] - $from::Pe64(ref mut $var) => $body.map($to::Pe64), - #[cfg(feature = "wasm")] - $from::Wasm(ref mut $var) => $body.map($to::Wasm), - #[cfg(feature = "xcoff")] - $from::Xcoff32(ref mut $var) => $body.map($to::Xcoff32), - #[cfg(feature = "xcoff")] - $from::Xcoff64(ref mut $var) => $body.map($to::Xcoff64), - } - }; -} - -/// Call `next` for a file format iterator. -macro_rules! next_inner { - ($inner:expr, $from:ident, $to:ident) => { - match $inner { - #[cfg(feature = "coff")] - $from::Coff(ref mut iter) => iter.next().map($to::Coff), - #[cfg(feature = "coff")] - $from::CoffBig(ref mut iter) => iter.next().map($to::CoffBig), - #[cfg(feature = "elf")] - $from::Elf32(ref mut iter) => iter.next().map($to::Elf32), - #[cfg(feature = "elf")] - $from::Elf64(ref mut iter) => iter.next().map($to::Elf64), - #[cfg(feature = "macho")] - $from::MachO32(ref mut iter) => iter.next().map($to::MachO32), - #[cfg(feature = "macho")] - $from::MachO64(ref mut iter) => iter.next().map($to::MachO64), - #[cfg(feature = "pe")] - $from::Pe32(ref mut iter) => iter.next().map($to::Pe32), - #[cfg(feature = "pe")] - $from::Pe64(ref mut iter) => iter.next().map($to::Pe64), - #[cfg(feature = "wasm")] - $from::Wasm(ref mut iter) => iter.next().map($to::Wasm), - #[cfg(feature = "xcoff")] - $from::Xcoff32(ref mut iter) => iter.next().map($to::Xcoff32), - #[cfg(feature = "xcoff")] - $from::Xcoff64(ref mut iter) => iter.next().map($to::Xcoff64), - } - }; -} - -/// An object file that can be any supported file format. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -#[non_exhaustive] -#[allow(missing_docs)] -pub enum File<'data, R: ReadRef<'data> = &'data [u8]> { - #[cfg(feature = "coff")] - Coff(coff::CoffFile<'data, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigFile<'data, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfFile32<'data, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfFile64<'data, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOFile32<'data, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOFile64<'data, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeFile32<'data, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeFile64<'data, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmFile<'data, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffFile32<'data, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffFile64<'data, R>), -} - -impl<'data, R: ReadRef<'data>> File<'data, R> { - /// Parse the raw file data. - pub fn parse(data: R) -> Result { - Ok(match FileKind::parse(data)? { - #[cfg(feature = "elf")] - FileKind::Elf32 => File::Elf32(elf::ElfFile32::parse(data)?), - #[cfg(feature = "elf")] - FileKind::Elf64 => File::Elf64(elf::ElfFile64::parse(data)?), - #[cfg(feature = "macho")] - FileKind::MachO32 => File::MachO32(macho::MachOFile32::parse(data)?), - #[cfg(feature = "macho")] - FileKind::MachO64 => File::MachO64(macho::MachOFile64::parse(data)?), - #[cfg(feature = "wasm")] - FileKind::Wasm => File::Wasm(wasm::WasmFile::parse(data)?), - #[cfg(feature = "pe")] - FileKind::Pe32 => File::Pe32(pe::PeFile32::parse(data)?), - #[cfg(feature = "pe")] - FileKind::Pe64 => File::Pe64(pe::PeFile64::parse(data)?), - #[cfg(feature = "coff")] - FileKind::Coff => File::Coff(coff::CoffFile::parse(data)?), - #[cfg(feature = "coff")] - FileKind::CoffBig => File::CoffBig(coff::CoffBigFile::parse(data)?), - #[cfg(feature = "xcoff")] - FileKind::Xcoff32 => File::Xcoff32(xcoff::XcoffFile32::parse(data)?), - #[cfg(feature = "xcoff")] - FileKind::Xcoff64 => File::Xcoff64(xcoff::XcoffFile64::parse(data)?), - #[allow(unreachable_patterns)] - _ => return Err(Error("Unsupported file format")), - }) - } - - /// Parse a Mach-O image from the dyld shared cache. - #[cfg(feature = "macho")] - pub fn parse_dyld_cache_image<'cache, E: Endian>( - image: &macho::DyldCacheImage<'data, 'cache, E, R>, - ) -> Result { - Ok(match image.cache.architecture().address_size() { - Some(AddressSize::U64) => { - File::MachO64(macho::MachOFile64::parse_dyld_cache_image(image)?) - } - Some(AddressSize::U32) => { - File::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?) - } - _ => return Err(Error("Unsupported file format")), - }) - } - - /// Return the file format. - pub fn format(&self) -> BinaryFormat { - match self { - #[cfg(feature = "coff")] - File::Coff(_) | File::CoffBig(_) => BinaryFormat::Coff, - #[cfg(feature = "elf")] - File::Elf32(_) | File::Elf64(_) => BinaryFormat::Elf, - #[cfg(feature = "macho")] - File::MachO32(_) | File::MachO64(_) => BinaryFormat::MachO, - #[cfg(feature = "pe")] - File::Pe32(_) | File::Pe64(_) => BinaryFormat::Pe, - #[cfg(feature = "wasm")] - File::Wasm(_) => BinaryFormat::Wasm, - #[cfg(feature = "xcoff")] - File::Xcoff32(_) | File::Xcoff64(_) => BinaryFormat::Xcoff, - } - } -} - -impl<'data, R: ReadRef<'data>> read::private::Sealed for File<'data, R> {} - -impl<'data, 'file, R> Object<'data, 'file> for File<'data, R> -where - 'data: 'file, - R: 'file + ReadRef<'data>, -{ - type Segment = Segment<'data, 'file, R>; - type SegmentIterator = SegmentIterator<'data, 'file, R>; - type Section = Section<'data, 'file, R>; - type SectionIterator = SectionIterator<'data, 'file, R>; - type Comdat = Comdat<'data, 'file, R>; - type ComdatIterator = ComdatIterator<'data, 'file, R>; - type Symbol = Symbol<'data, 'file, R>; - type SymbolIterator = SymbolIterator<'data, 'file, R>; - type SymbolTable = SymbolTable<'data, 'file, R>; - type DynamicRelocationIterator = DynamicRelocationIterator<'data, 'file, R>; - - fn architecture(&self) -> Architecture { - with_inner!(self, File, |x| x.architecture()) - } - - fn sub_architecture(&self) -> Option { - with_inner!(self, File, |x| x.sub_architecture()) - } - - fn is_little_endian(&self) -> bool { - with_inner!(self, File, |x| x.is_little_endian()) - } - - fn is_64(&self) -> bool { - with_inner!(self, File, |x| x.is_64()) - } - - fn kind(&self) -> ObjectKind { - with_inner!(self, File, |x| x.kind()) - } - - fn segments(&'file self) -> SegmentIterator<'data, 'file, R> { - SegmentIterator { - inner: map_inner!(self, File, SegmentIteratorInternal, |x| x.segments()), - } - } - - fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option> { - map_inner_option!(self, File, SectionInternal, |x| x - .section_by_name_bytes(section_name)) - .map(|inner| Section { inner }) - } - - fn section_by_index(&'file self, index: SectionIndex) -> Result> { - map_inner_option!(self, File, SectionInternal, |x| x.section_by_index(index)) - .map(|inner| Section { inner }) - } - - fn sections(&'file self) -> SectionIterator<'data, 'file, R> { - SectionIterator { - inner: map_inner!(self, File, SectionIteratorInternal, |x| x.sections()), - } - } - - fn comdats(&'file self) -> ComdatIterator<'data, 'file, R> { - ComdatIterator { - inner: map_inner!(self, File, ComdatIteratorInternal, |x| x.comdats()), - } - } - - fn symbol_by_index(&'file self, index: SymbolIndex) -> Result> { - map_inner_option!(self, File, SymbolInternal, |x| x - .symbol_by_index(index) - .map(|x| (x, PhantomData))) - .map(|inner| Symbol { inner }) - } - - fn symbols(&'file self) -> SymbolIterator<'data, 'file, R> { - SymbolIterator { - inner: map_inner!(self, File, SymbolIteratorInternal, |x| ( - x.symbols(), - PhantomData - )), - } - } - - fn symbol_table(&'file self) -> Option> { - map_inner_option!(self, File, SymbolTableInternal, |x| x - .symbol_table() - .map(|x| (x, PhantomData))) - .map(|inner| SymbolTable { inner }) - } - - fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file, R> { - SymbolIterator { - inner: map_inner!(self, File, SymbolIteratorInternal, |x| ( - x.dynamic_symbols(), - PhantomData - )), - } - } - - fn dynamic_symbol_table(&'file self) -> Option> { - map_inner_option!(self, File, SymbolTableInternal, |x| x - .dynamic_symbol_table() - .map(|x| (x, PhantomData))) - .map(|inner| SymbolTable { inner }) - } - - #[cfg(feature = "elf")] - fn dynamic_relocations(&'file self) -> Option> { - let inner = match self { - File::Elf32(ref elf) => { - DynamicRelocationIteratorInternal::Elf32(elf.dynamic_relocations()?) - } - File::Elf64(ref elf) => { - DynamicRelocationIteratorInternal::Elf64(elf.dynamic_relocations()?) - } - #[allow(unreachable_patterns)] - _ => return None, - }; - Some(DynamicRelocationIterator { inner }) - } - - #[cfg(not(feature = "elf"))] - fn dynamic_relocations(&'file self) -> Option> { - None - } - - fn symbol_map(&self) -> SymbolMap> { - with_inner!(self, File, |x| x.symbol_map()) - } - - fn object_map(&self) -> ObjectMap<'data> { - with_inner!(self, File, |x| x.object_map()) - } - - fn imports(&self) -> Result>> { - with_inner!(self, File, |x| x.imports()) - } - - fn exports(&self) -> Result>> { - with_inner!(self, File, |x| x.exports()) - } - - fn has_debug_symbols(&self) -> bool { - with_inner!(self, File, |x| x.has_debug_symbols()) - } - - #[inline] - fn mach_uuid(&self) -> Result> { - with_inner!(self, File, |x| x.mach_uuid()) - } - - #[inline] - fn build_id(&self) -> Result> { - with_inner!(self, File, |x| x.build_id()) - } - - #[inline] - fn gnu_debuglink(&self) -> Result> { - with_inner!(self, File, |x| x.gnu_debuglink()) - } - - #[inline] - fn gnu_debugaltlink(&self) -> Result> { - with_inner!(self, File, |x| x.gnu_debugaltlink()) - } - - #[inline] - fn pdb_info(&self) -> Result>> { - with_inner!(self, File, |x| x.pdb_info()) - } - - fn relative_address_base(&self) -> u64 { - with_inner!(self, File, |x| x.relative_address_base()) - } - - fn entry(&self) -> u64 { - with_inner!(self, File, |x| x.entry()) - } - - fn flags(&self) -> FileFlags { - with_inner!(self, File, |x| x.flags()) - } -} - -/// An iterator for the loadable segments in a [`File`]. -#[derive(Debug)] -pub struct SegmentIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: SegmentIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum SegmentIteratorInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffSegmentIterator<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigSegmentIterator<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfSegmentIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfSegmentIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOSegmentIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOSegmentIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeSegmentIterator32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeSegmentIterator64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmSegmentIterator<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffSegmentIterator32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffSegmentIterator64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for SegmentIterator<'data, 'file, R> { - type Item = Segment<'data, 'file, R>; - - fn next(&mut self) -> Option { - next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal) - .map(|inner| Segment { inner }) - } -} - -/// A loadable segment in a [`File`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -pub struct Segment<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: SegmentInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum SegmentInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffSegment<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigSegment<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfSegment32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfSegment64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOSegment32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOSegment64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeSegment32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeSegment64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmSegment<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffSegment32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffSegment64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Segment<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // It's painful to do much better than this - let mut s = f.debug_struct("Segment"); - match self.name() { - Ok(Some(ref name)) => { - s.field("name", name); - } - Ok(None) => {} - Err(_) => { - s.field("name", &""); - } - } - s.field("address", &self.address()) - .field("size", &self.size()) - .finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Segment<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSegment<'data> for Segment<'data, 'file, R> { - fn address(&self) -> u64 { - with_inner!(self.inner, SegmentInternal, |x| x.address()) - } - - fn size(&self) -> u64 { - with_inner!(self.inner, SegmentInternal, |x| x.size()) - } - - fn align(&self) -> u64 { - with_inner!(self.inner, SegmentInternal, |x| x.align()) - } - - fn file_range(&self) -> (u64, u64) { - with_inner!(self.inner, SegmentInternal, |x| x.file_range()) - } - - fn data(&self) -> Result<&'data [u8]> { - with_inner!(self.inner, SegmentInternal, |x| x.data()) - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size)) - } - - fn name_bytes(&self) -> Result> { - with_inner!(self.inner, SegmentInternal, |x| x.name_bytes()) - } - - fn name(&self) -> Result> { - with_inner!(self.inner, SegmentInternal, |x| x.name()) - } - - fn flags(&self) -> SegmentFlags { - with_inner!(self.inner, SegmentInternal, |x| x.flags()) - } -} - -/// An iterator for the sections in a [`File`]. -#[derive(Debug)] -pub struct SectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: SectionIteratorInternal<'data, 'file, R>, -} - -// we wrap our enums in a struct so that they are kept private. -#[derive(Debug)] -enum SectionIteratorInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffSectionIterator<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigSectionIterator<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfSectionIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfSectionIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOSectionIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOSectionIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeSectionIterator32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeSectionIterator64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmSectionIterator<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffSectionIterator32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffSectionIterator64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionIterator<'data, 'file, R> { - type Item = Section<'data, 'file, R>; - - fn next(&mut self) -> Option { - next_inner!(self.inner, SectionIteratorInternal, SectionInternal) - .map(|inner| Section { inner }) - } -} - -/// A section in a [`File`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -pub struct Section<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: SectionInternal<'data, 'file, R>, -} - -enum SectionInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffSection<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigSection<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfSection32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfSection64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOSection32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOSection64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeSection32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeSection64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmSection<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffSection32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffSection64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Section<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // It's painful to do much better than this - let mut s = f.debug_struct("Section"); - match self.segment_name() { - Ok(Some(ref name)) => { - s.field("segment", name); - } - Ok(None) => {} - Err(_) => { - s.field("segment", &""); - } - } - s.field("name", &self.name().unwrap_or("")) - .field("address", &self.address()) - .field("size", &self.size()) - .field("align", &self.align()) - .field("kind", &self.kind()) - .field("flags", &self.flags()) - .finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Section<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for Section<'data, 'file, R> { - type RelocationIterator = SectionRelocationIterator<'data, 'file, R>; - - fn index(&self) -> SectionIndex { - with_inner!(self.inner, SectionInternal, |x| x.index()) - } - - fn address(&self) -> u64 { - with_inner!(self.inner, SectionInternal, |x| x.address()) - } - - fn size(&self) -> u64 { - with_inner!(self.inner, SectionInternal, |x| x.size()) - } - - fn align(&self) -> u64 { - with_inner!(self.inner, SectionInternal, |x| x.align()) - } - - fn file_range(&self) -> Option<(u64, u64)> { - with_inner!(self.inner, SectionInternal, |x| x.file_range()) - } - - fn data(&self) -> Result<&'data [u8]> { - with_inner!(self.inner, SectionInternal, |x| x.data()) - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size)) - } - - fn compressed_file_range(&self) -> Result { - with_inner!(self.inner, SectionInternal, |x| x.compressed_file_range()) - } - - fn compressed_data(&self) -> Result> { - with_inner!(self.inner, SectionInternal, |x| x.compressed_data()) - } - - fn name_bytes(&self) -> Result<&[u8]> { - with_inner!(self.inner, SectionInternal, |x| x.name_bytes()) - } - - fn name(&self) -> Result<&str> { - with_inner!(self.inner, SectionInternal, |x| x.name()) - } - - fn segment_name_bytes(&self) -> Result> { - with_inner!(self.inner, SectionInternal, |x| x.segment_name_bytes()) - } - - fn segment_name(&self) -> Result> { - with_inner!(self.inner, SectionInternal, |x| x.segment_name()) - } - - fn kind(&self) -> SectionKind { - with_inner!(self.inner, SectionInternal, |x| x.kind()) - } - - fn relocations(&self) -> SectionRelocationIterator<'data, 'file, R> { - SectionRelocationIterator { - inner: map_inner!( - self.inner, - SectionInternal, - SectionRelocationIteratorInternal, - |x| x.relocations() - ), - } - } - - fn flags(&self) -> SectionFlags { - with_inner!(self.inner, SectionInternal, |x| x.flags()) - } -} - -/// An iterator for the COMDAT section groups in a [`File`]. -#[derive(Debug)] -pub struct ComdatIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: ComdatIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum ComdatIteratorInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffComdatIterator<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigComdatIterator<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfComdatIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfComdatIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOComdatIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOComdatIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeComdatIterator32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeComdatIterator64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmComdatIterator<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffComdatIterator32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffComdatIterator64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatIterator<'data, 'file, R> { - type Item = Comdat<'data, 'file, R>; - - fn next(&mut self) -> Option { - next_inner!(self.inner, ComdatIteratorInternal, ComdatInternal) - .map(|inner| Comdat { inner }) - } -} - -/// A COMDAT section group in a [`File`]. -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -pub struct Comdat<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: ComdatInternal<'data, 'file, R>, -} - -enum ComdatInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffComdat<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigComdat<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfComdat32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfComdat64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOComdat32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOComdat64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeComdat32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeComdat64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmComdat<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffComdat32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffComdat64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Comdat<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut s = f.debug_struct("Comdat"); - s.field("symbol", &self.symbol()) - .field("name", &self.name().unwrap_or("")) - .field("kind", &self.kind()) - .finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Comdat<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectComdat<'data> for Comdat<'data, 'file, R> { - type SectionIterator = ComdatSectionIterator<'data, 'file, R>; - - fn kind(&self) -> ComdatKind { - with_inner!(self.inner, ComdatInternal, |x| x.kind()) - } - - fn symbol(&self) -> SymbolIndex { - with_inner!(self.inner, ComdatInternal, |x| x.symbol()) - } - - fn name_bytes(&self) -> Result<&[u8]> { - with_inner!(self.inner, ComdatInternal, |x| x.name_bytes()) - } - - fn name(&self) -> Result<&str> { - with_inner!(self.inner, ComdatInternal, |x| x.name()) - } - - fn sections(&self) -> ComdatSectionIterator<'data, 'file, R> { - ComdatSectionIterator { - inner: map_inner!( - self.inner, - ComdatInternal, - ComdatSectionIteratorInternal, - |x| x.sections() - ), - } - } -} - -/// An iterator for the sections in a [`Comdat`]. -#[derive(Debug)] -pub struct ComdatSectionIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: ComdatSectionIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum ComdatSectionIteratorInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffComdatSectionIterator<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigComdatSectionIterator<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfComdatSectionIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfComdatSectionIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachOComdatSectionIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachOComdatSectionIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeComdatSectionIterator32<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeComdatSectionIterator64<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmComdatSectionIterator<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffComdatSectionIterator32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffComdatSectionIterator64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatSectionIterator<'data, 'file, R> { - type Item = SectionIndex; - - fn next(&mut self) -> Option { - with_inner_mut!(self.inner, ComdatSectionIteratorInternal, |x| x.next()) - } -} - -/// A symbol table in a [`File`]. -/// -/// Most functionality is provided by the [`ObjectSymbolTable`] trait implementation. -#[derive(Debug)] -pub struct SymbolTable<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - inner: SymbolTableInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum SymbolTableInternal<'data, 'file, R> -where - R: ReadRef<'data>, -{ - #[cfg(feature = "coff")] - Coff((coff::CoffSymbolTable<'data, 'file, R>, PhantomData)), - #[cfg(feature = "coff")] - CoffBig((coff::CoffBigSymbolTable<'data, 'file, R>, PhantomData)), - #[cfg(feature = "elf")] - Elf32( - ( - elf::ElfSymbolTable32<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "elf")] - Elf64( - ( - elf::ElfSymbolTable64<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "macho")] - MachO32( - ( - macho::MachOSymbolTable32<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "macho")] - MachO64( - ( - macho::MachOSymbolTable64<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "pe")] - Pe32((coff::CoffSymbolTable<'data, 'file, R>, PhantomData)), - #[cfg(feature = "pe")] - Pe64((coff::CoffSymbolTable<'data, 'file, R>, PhantomData)), - #[cfg(feature = "wasm")] - Wasm((wasm::WasmSymbolTable<'data, 'file>, PhantomData)), - #[cfg(feature = "xcoff")] - Xcoff32((xcoff::XcoffSymbolTable32<'data, 'file, R>, PhantomData)), - #[cfg(feature = "xcoff")] - Xcoff64((xcoff::XcoffSymbolTable64<'data, 'file, R>, PhantomData)), -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for SymbolTable<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSymbolTable<'data> for SymbolTable<'data, 'file, R> { - type Symbol = Symbol<'data, 'file, R>; - type SymbolIterator = SymbolIterator<'data, 'file, R>; - - fn symbols(&self) -> Self::SymbolIterator { - SymbolIterator { - inner: map_inner!( - self.inner, - SymbolTableInternal, - SymbolIteratorInternal, - |x| (x.0.symbols(), PhantomData) - ), - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> Result { - map_inner_option!(self.inner, SymbolTableInternal, SymbolInternal, |x| x - .0 - .symbol_by_index(index) - .map(|x| (x, PhantomData))) - .map(|inner| Symbol { inner }) - } -} - -/// An iterator for the symbols in a [`SymbolTable`]. -#[derive(Debug)] -pub struct SymbolIterator<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - inner: SymbolIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum SymbolIteratorInternal<'data, 'file, R> -where - R: ReadRef<'data>, -{ - #[cfg(feature = "coff")] - Coff((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData)), - #[cfg(feature = "coff")] - CoffBig((coff::CoffBigSymbolIterator<'data, 'file, R>, PhantomData)), - #[cfg(feature = "elf")] - Elf32( - ( - elf::ElfSymbolIterator32<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "elf")] - Elf64( - ( - elf::ElfSymbolIterator64<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "macho")] - MachO32( - ( - macho::MachOSymbolIterator32<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "macho")] - MachO64( - ( - macho::MachOSymbolIterator64<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "pe")] - Pe32((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData)), - #[cfg(feature = "pe")] - Pe64((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData)), - #[cfg(feature = "wasm")] - Wasm((wasm::WasmSymbolIterator<'data, 'file>, PhantomData)), - #[cfg(feature = "xcoff")] - Xcoff32( - ( - xcoff::XcoffSymbolIterator32<'data, 'file, R>, - PhantomData, - ), - ), - #[cfg(feature = "xcoff")] - Xcoff64( - ( - xcoff::XcoffSymbolIterator64<'data, 'file, R>, - PhantomData, - ), - ), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> { - type Item = Symbol<'data, 'file, R>; - - fn next(&mut self) -> Option { - map_inner_option_mut!(self.inner, SymbolIteratorInternal, SymbolInternal, |iter| { - iter.0.next().map(|x| (x, PhantomData)) - }) - .map(|inner| Symbol { inner }) - } -} - -/// An symbol in a [`SymbolTable`]. -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -pub struct Symbol<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - inner: SymbolInternal<'data, 'file, R>, -} - -enum SymbolInternal<'data, 'file, R> -where - R: ReadRef<'data>, -{ - #[cfg(feature = "coff")] - Coff((coff::CoffSymbol<'data, 'file, R>, PhantomData)), - #[cfg(feature = "coff")] - CoffBig((coff::CoffBigSymbol<'data, 'file, R>, PhantomData)), - #[cfg(feature = "elf")] - Elf32( - ( - elf::ElfSymbol32<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "elf")] - Elf64( - ( - elf::ElfSymbol64<'data, 'file, Endianness, R>, - PhantomData, - ), - ), - #[cfg(feature = "macho")] - MachO32( - ( - macho::MachOSymbol32<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "macho")] - MachO64( - ( - macho::MachOSymbol64<'data, 'file, Endianness, R>, - PhantomData<()>, - ), - ), - #[cfg(feature = "pe")] - Pe32((coff::CoffSymbol<'data, 'file, R>, PhantomData)), - #[cfg(feature = "pe")] - Pe64((coff::CoffSymbol<'data, 'file, R>, PhantomData)), - #[cfg(feature = "wasm")] - Wasm((wasm::WasmSymbol<'data, 'file>, PhantomData)), - #[cfg(feature = "xcoff")] - Xcoff32((xcoff::XcoffSymbol32<'data, 'file, R>, PhantomData)), - #[cfg(feature = "xcoff")] - Xcoff64((xcoff::XcoffSymbol64<'data, 'file, R>, PhantomData)), -} - -impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Symbol<'data, 'file, R> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Symbol") - .field("name", &self.name().unwrap_or("")) - .field("address", &self.address()) - .field("size", &self.size()) - .field("kind", &self.kind()) - .field("section", &self.section()) - .field("scope", &self.scope()) - .field("weak", &self.is_weak()) - .field("flags", &self.flags()) - .finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for Symbol<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for Symbol<'data, 'file, R> { - fn index(&self) -> SymbolIndex { - with_inner!(self.inner, SymbolInternal, |x| x.0.index()) - } - - fn name_bytes(&self) -> Result<&'data [u8]> { - with_inner!(self.inner, SymbolInternal, |x| x.0.name_bytes()) - } - - fn name(&self) -> Result<&'data str> { - with_inner!(self.inner, SymbolInternal, |x| x.0.name()) - } - - fn address(&self) -> u64 { - with_inner!(self.inner, SymbolInternal, |x| x.0.address()) - } - - fn size(&self) -> u64 { - with_inner!(self.inner, SymbolInternal, |x| x.0.size()) - } - - fn kind(&self) -> SymbolKind { - with_inner!(self.inner, SymbolInternal, |x| x.0.kind()) - } - - fn section(&self) -> SymbolSection { - with_inner!(self.inner, SymbolInternal, |x| x.0.section()) - } - - fn is_undefined(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_undefined()) - } - - fn is_definition(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_definition()) - } - - fn is_common(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_common()) - } - - fn is_weak(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_weak()) - } - - fn scope(&self) -> SymbolScope { - with_inner!(self.inner, SymbolInternal, |x| x.0.scope()) - } - - fn is_global(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_global()) - } - - fn is_local(&self) -> bool { - with_inner!(self.inner, SymbolInternal, |x| x.0.is_local()) - } - - fn flags(&self) -> SymbolFlags { - with_inner!(self.inner, SymbolInternal, |x| x.0.flags()) - } -} - -/// An iterator for the dynamic relocation entries in a [`File`]. -#[derive(Debug)] -pub struct DynamicRelocationIterator<'data, 'file, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - inner: DynamicRelocationIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum DynamicRelocationIteratorInternal<'data, 'file, R> -where - R: ReadRef<'data>, -{ - #[cfg(feature = "elf")] - Elf32(elf::ElfDynamicRelocationIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfDynamicRelocationIterator64<'data, 'file, Endianness, R>), - // We need to always use the lifetime parameters. - #[allow(unused)] - None(PhantomData<(&'data (), &'file (), R)>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for DynamicRelocationIterator<'data, 'file, R> { - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - match self.inner { - #[cfg(feature = "elf")] - DynamicRelocationIteratorInternal::Elf32(ref mut elf) => elf.next(), - #[cfg(feature = "elf")] - DynamicRelocationIteratorInternal::Elf64(ref mut elf) => elf.next(), - DynamicRelocationIteratorInternal::None(_) => None, - } - } -} - -/// An iterator for the relocation entries in a [`Section`]. -#[derive(Debug)] -pub struct SectionRelocationIterator<'data, 'file, R: ReadRef<'data> = &'data [u8]> { - inner: SectionRelocationIteratorInternal<'data, 'file, R>, -} - -#[derive(Debug)] -enum SectionRelocationIteratorInternal<'data, 'file, R: ReadRef<'data>> { - #[cfg(feature = "coff")] - Coff(coff::CoffRelocationIterator<'data, 'file, R>), - #[cfg(feature = "coff")] - CoffBig(coff::CoffBigRelocationIterator<'data, 'file, R>), - #[cfg(feature = "elf")] - Elf32(elf::ElfSectionRelocationIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "elf")] - Elf64(elf::ElfSectionRelocationIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO32(macho::MachORelocationIterator32<'data, 'file, Endianness, R>), - #[cfg(feature = "macho")] - MachO64(macho::MachORelocationIterator64<'data, 'file, Endianness, R>), - #[cfg(feature = "pe")] - Pe32(pe::PeRelocationIterator<'data, 'file, R>), - #[cfg(feature = "pe")] - Pe64(pe::PeRelocationIterator<'data, 'file, R>), - #[cfg(feature = "wasm")] - Wasm(wasm::WasmRelocationIterator<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff32(xcoff::XcoffRelocationIterator32<'data, 'file, R>), - #[cfg(feature = "xcoff")] - Xcoff64(xcoff::XcoffRelocationIterator64<'data, 'file, R>), -} - -impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionRelocationIterator<'data, 'file, R> { - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - with_inner_mut!(self.inner, SectionRelocationIteratorInternal, |x| x.next()) - } -} diff --git a/vendor/object/src/read/archive.rs b/vendor/object/src/read/archive.rs deleted file mode 100644 index 5d4ec4a..0000000 --- a/vendor/object/src/read/archive.rs +++ /dev/null @@ -1,759 +0,0 @@ -//! Support for archive files. -//! -//! ## Example -//! ```no_run -//! use object::{Object, ObjectSection}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads an archive and displays the name of each member. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let file = object::read::archive::ArchiveFile::parse(&*data)?; -//! for member in file.members() { -//! let member = member?; -//! println!("{}", String::from_utf8_lossy(member.name())); -//! } -//! # } -//! Ok(()) -//! } -//! ``` - -use core::convert::TryInto; - -use crate::archive; -use crate::read::{self, Bytes, Error, ReadError, ReadRef}; - -/// The kind of archive format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ArchiveKind { - /// There are no special files that indicate the archive format. - Unknown, - /// The GNU (or System V) archive format. - Gnu, - /// The GNU (or System V) archive format with 64-bit symbol table. - Gnu64, - /// The BSD archive format. - Bsd, - /// The BSD archive format with 64-bit symbol table. - /// - /// This is used for Darwin. - Bsd64, - /// The Windows COFF archive format. - Coff, - /// The AIX big archive format. - AixBig, -} - -/// The list of members in the archive. -#[derive(Debug, Clone, Copy)] -enum Members<'data> { - Common { - offset: u64, - end_offset: u64, - }, - AixBig { - index: &'data [archive::AixMemberOffset], - }, -} - -/// A partially parsed archive file. -#[derive(Debug, Clone, Copy)] -pub struct ArchiveFile<'data, R: ReadRef<'data> = &'data [u8]> { - data: R, - kind: ArchiveKind, - members: Members<'data>, - symbols: (u64, u64), - names: &'data [u8], -} - -impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> { - /// Parse the archive header and special members. - pub fn parse(data: R) -> read::Result { - let len = data.len().read_error("Unknown archive length")?; - let mut tail = 0; - let magic = data - .read_bytes(&mut tail, archive::MAGIC.len() as u64) - .read_error("Invalid archive size")?; - - if magic == archive::AIX_BIG_MAGIC { - return Self::parse_aixbig(data); - } else if magic != archive::MAGIC { - return Err(Error("Unsupported archive identifier")); - } - - let mut members_offset = tail; - let members_end_offset = len; - - let mut file = ArchiveFile { - data, - kind: ArchiveKind::Unknown, - members: Members::Common { - offset: 0, - end_offset: 0, - }, - symbols: (0, 0), - names: &[], - }; - - // The first few members may be special, so parse them. - // GNU has: - // - "/" or "/SYM64/": symbol table (optional) - // - "//": names table (optional) - // COFF has: - // - "/": first linker member - // - "/": second linker member - // - "//": names table - // BSD has: - // - "__.SYMDEF" or "__.SYMDEF SORTED": symbol table (optional) - // BSD 64-bit has: - // - "__.SYMDEF_64" or "__.SYMDEF_64 SORTED": symbol table (optional) - // BSD may use the extended name for the symbol table. This is handled - // by `ArchiveMember::parse`. - if tail < len { - let member = ArchiveMember::parse(data, &mut tail, &[])?; - if member.name == b"/" { - // GNU symbol table (unless we later determine this is COFF). - file.kind = ArchiveKind::Gnu; - file.symbols = member.file_range(); - members_offset = tail; - - if tail < len { - let member = ArchiveMember::parse(data, &mut tail, &[])?; - if member.name == b"/" { - // COFF linker member. - file.kind = ArchiveKind::Coff; - file.symbols = member.file_range(); - members_offset = tail; - - if tail < len { - let member = ArchiveMember::parse(data, &mut tail, &[])?; - if member.name == b"//" { - // COFF names table. - file.names = member.data(data)?; - members_offset = tail; - } - } - } else if member.name == b"//" { - // GNU names table. - file.names = member.data(data)?; - members_offset = tail; - } - } - } else if member.name == b"/SYM64/" { - // GNU 64-bit symbol table. - file.kind = ArchiveKind::Gnu64; - file.symbols = member.file_range(); - members_offset = tail; - - if tail < len { - let member = ArchiveMember::parse(data, &mut tail, &[])?; - if member.name == b"//" { - // GNU names table. - file.names = member.data(data)?; - members_offset = tail; - } - } - } else if member.name == b"//" { - // GNU names table. - file.kind = ArchiveKind::Gnu; - file.names = member.data(data)?; - members_offset = tail; - } else if member.name == b"__.SYMDEF" || member.name == b"__.SYMDEF SORTED" { - // BSD symbol table. - file.kind = ArchiveKind::Bsd; - file.symbols = member.file_range(); - members_offset = tail; - } else if member.name == b"__.SYMDEF_64" || member.name == b"__.SYMDEF_64 SORTED" { - // BSD 64-bit symbol table. - file.kind = ArchiveKind::Bsd64; - file.symbols = member.file_range(); - members_offset = tail; - } else { - // TODO: This could still be a BSD file. We leave this as unknown for now. - } - } - file.members = Members::Common { - offset: members_offset, - end_offset: members_end_offset, - }; - Ok(file) - } - - fn parse_aixbig(data: R) -> read::Result { - let mut tail = 0; - - let file_header = data - .read::(&mut tail) - .read_error("Invalid AIX big archive file header")?; - // Caller already validated this. - debug_assert_eq!(file_header.magic, archive::AIX_BIG_MAGIC); - - let mut file = ArchiveFile { - data, - kind: ArchiveKind::AixBig, - members: Members::AixBig { index: &[] }, - symbols: (0, 0), - names: &[], - }; - - // Read the span of symbol table. - let symtbl64 = parse_u64_digits(&file_header.gst64off, 10) - .read_error("Invalid offset to 64-bit symbol table in AIX big archive")?; - if symtbl64 > 0 { - // The symbol table is also a file with header. - let member = ArchiveMember::parse_aixbig(data, symtbl64)?; - file.symbols = member.file_range(); - } else { - let symtbl = parse_u64_digits(&file_header.gstoff, 10) - .read_error("Invalid offset to symbol table in AIX big archive")?; - if symtbl > 0 { - // The symbol table is also a file with header. - let member = ArchiveMember::parse_aixbig(data, symtbl)?; - file.symbols = member.file_range(); - } - } - - // Big archive member index table lists file entries with offsets and names. - // To avoid potential infinite loop (members are double-linked list), the - // iterator goes through the index instead of real members. - let member_table_offset = parse_u64_digits(&file_header.memoff, 10) - .read_error("Invalid offset for member table of AIX big archive")?; - if member_table_offset == 0 { - // The offset would be zero if archive contains no file. - return Ok(file); - } - - // The member index table is also a file with header. - let member = ArchiveMember::parse_aixbig(data, member_table_offset)?; - let mut member_data = Bytes(member.data(data)?); - - // Structure of member index table: - // Number of entries (20 bytes) - // Offsets of each entry (20*N bytes) - // Names string table (the rest of bytes to fill size defined in header) - let members_count_bytes = member_data - .read_slice::(20) - .read_error("Missing member count in AIX big archive")?; - let members_count = parse_u64_digits(members_count_bytes, 10) - .and_then(|size| size.try_into().ok()) - .read_error("Invalid member count in AIX big archive")?; - let index = member_data - .read_slice::(members_count) - .read_error("Member count overflow in AIX big archive")?; - file.members = Members::AixBig { index }; - - Ok(file) - } - - /// Return the archive format. - #[inline] - pub fn kind(&self) -> ArchiveKind { - self.kind - } - - /// Iterate over the members of the archive. - /// - /// This does not return special members. - #[inline] - pub fn members(&self) -> ArchiveMemberIterator<'data, R> { - ArchiveMemberIterator { - data: self.data, - members: self.members, - names: self.names, - } - } -} - -/// An iterator over the members of an archive. -#[derive(Debug)] -pub struct ArchiveMemberIterator<'data, R: ReadRef<'data> = &'data [u8]> { - data: R, - members: Members<'data>, - names: &'data [u8], -} - -impl<'data, R: ReadRef<'data>> Iterator for ArchiveMemberIterator<'data, R> { - type Item = read::Result>; - - fn next(&mut self) -> Option { - match &mut self.members { - Members::Common { - ref mut offset, - ref mut end_offset, - } => { - if *offset >= *end_offset { - return None; - } - let member = ArchiveMember::parse(self.data, offset, self.names); - if member.is_err() { - *offset = *end_offset; - } - Some(member) - } - Members::AixBig { ref mut index } => match **index { - [] => None, - [ref first, ref rest @ ..] => { - *index = rest; - let member = ArchiveMember::parse_aixbig_index(self.data, first); - if member.is_err() { - *index = &[]; - } - Some(member) - } - }, - } - } -} - -/// An archive member header. -#[derive(Debug, Clone, Copy)] -enum MemberHeader<'data> { - /// Common header used by many formats. - Common(&'data archive::Header), - /// AIX big archive header - AixBig(&'data archive::AixHeader), -} - -/// A partially parsed archive member. -#[derive(Debug)] -pub struct ArchiveMember<'data> { - header: MemberHeader<'data>, - name: &'data [u8], - offset: u64, - size: u64, -} - -impl<'data> ArchiveMember<'data> { - /// Parse the member header, name, and file data in an archive with the common format. - /// - /// This reads the extended name (if any) and adjusts the file size. - fn parse>( - data: R, - offset: &mut u64, - names: &'data [u8], - ) -> read::Result { - let header = data - .read::(offset) - .read_error("Invalid archive member header")?; - if header.terminator != archive::TERMINATOR { - return Err(Error("Invalid archive terminator")); - } - - let mut file_offset = *offset; - let mut file_size = - parse_u64_digits(&header.size, 10).read_error("Invalid archive member size")?; - *offset = offset - .checked_add(file_size) - .read_error("Archive member size is too large")?; - // Entries are padded to an even number of bytes. - if (file_size & 1) != 0 { - *offset = offset.saturating_add(1); - } - - let name = if header.name[0] == b'/' && (header.name[1] as char).is_ascii_digit() { - // Read file name from the names table. - parse_sysv_extended_name(&header.name[1..], names) - .read_error("Invalid archive extended name offset")? - } else if &header.name[..3] == b"#1/" && (header.name[3] as char).is_ascii_digit() { - // Read file name from the start of the file data. - parse_bsd_extended_name(&header.name[3..], data, &mut file_offset, &mut file_size) - .read_error("Invalid archive extended name length")? - } else if header.name[0] == b'/' { - let name_len = memchr::memchr(b' ', &header.name).unwrap_or(header.name.len()); - &header.name[..name_len] - } else { - let name_len = memchr::memchr(b'/', &header.name) - .or_else(|| memchr::memchr(b' ', &header.name)) - .unwrap_or(header.name.len()); - &header.name[..name_len] - }; - - Ok(ArchiveMember { - header: MemberHeader::Common(header), - name, - offset: file_offset, - size: file_size, - }) - } - - /// Parse a member index entry in an AIX big archive, - /// and then parse the member header, name, and file data. - fn parse_aixbig_index>( - data: R, - index: &archive::AixMemberOffset, - ) -> read::Result { - let offset = parse_u64_digits(&index.0, 10) - .read_error("Invalid AIX big archive file member offset")?; - Self::parse_aixbig(data, offset) - } - - /// Parse the member header, name, and file data in an AIX big archive. - fn parse_aixbig>(data: R, mut offset: u64) -> read::Result { - // The format was described at - // https://www.ibm.com/docs/en/aix/7.3?topic=formats-ar-file-format-big - let header = data - .read::(&mut offset) - .read_error("Invalid AIX big archive member header")?; - let name_length = parse_u64_digits(&header.namlen, 10) - .read_error("Invalid AIX big archive member name length")?; - let name = data - .read_bytes(&mut offset, name_length) - .read_error("Invalid AIX big archive member name")?; - - // The actual data for a file member begins at the first even-byte boundary beyond the - // member header and continues for the number of bytes specified by the ar_size field. The - // ar command inserts null bytes for padding where necessary. - if offset & 1 != 0 { - offset = offset.saturating_add(1); - } - // Because of the even-byte boundary, we have to read and check terminator after header. - let terminator = data - .read_bytes(&mut offset, 2) - .read_error("Invalid AIX big archive terminator")?; - if terminator != archive::TERMINATOR { - return Err(Error("Invalid AIX big archive terminator")); - } - - let size = parse_u64_digits(&header.size, 10) - .read_error("Invalid archive member size in AIX big archive")?; - Ok(ArchiveMember { - header: MemberHeader::AixBig(header), - name, - offset, - size, - }) - } - - /// Return the raw header that is common to many archive formats. - /// - /// Returns `None` if this archive does not use the common header format. - #[inline] - pub fn header(&self) -> Option<&'data archive::Header> { - match self.header { - MemberHeader::Common(header) => Some(header), - _ => None, - } - } - - /// Return the raw header for AIX big archives. - /// - /// Returns `None` if this is not an AIX big archive. - #[inline] - pub fn aix_header(&self) -> Option<&'data archive::AixHeader> { - match self.header { - MemberHeader::AixBig(header) => Some(header), - _ => None, - } - } - - /// Return the parsed file name. - /// - /// This may be an extended file name. - #[inline] - pub fn name(&self) -> &'data [u8] { - self.name - } - - /// Parse the file modification timestamp from the header. - #[inline] - pub fn date(&self) -> Option { - match &self.header { - MemberHeader::Common(header) => parse_u64_digits(&header.date, 10), - MemberHeader::AixBig(header) => parse_u64_digits(&header.date, 10), - } - } - - /// Parse the user ID from the header. - #[inline] - pub fn uid(&self) -> Option { - match &self.header { - MemberHeader::Common(header) => parse_u64_digits(&header.uid, 10), - MemberHeader::AixBig(header) => parse_u64_digits(&header.uid, 10), - } - } - - /// Parse the group ID from the header. - #[inline] - pub fn gid(&self) -> Option { - match &self.header { - MemberHeader::Common(header) => parse_u64_digits(&header.gid, 10), - MemberHeader::AixBig(header) => parse_u64_digits(&header.gid, 10), - } - } - - /// Parse the file mode from the header. - #[inline] - pub fn mode(&self) -> Option { - match &self.header { - MemberHeader::Common(header) => parse_u64_digits(&header.mode, 8), - MemberHeader::AixBig(header) => parse_u64_digits(&header.mode, 8), - } - } - - /// Return the offset and size of the file data. - pub fn file_range(&self) -> (u64, u64) { - (self.offset, self.size) - } - - /// Return the file data. - #[inline] - pub fn data>(&self, data: R) -> read::Result<&'data [u8]> { - data.read_bytes_at(self.offset, self.size) - .read_error("Archive member size is too large") - } -} - -// Ignores bytes starting from the first space. -fn parse_u64_digits(digits: &[u8], radix: u32) -> Option { - if let [b' ', ..] = digits { - return None; - } - let mut result: u64 = 0; - for &c in digits { - if c == b' ' { - return Some(result); - } else { - let x = (c as char).to_digit(radix)?; - result = result - .checked_mul(u64::from(radix))? - .checked_add(u64::from(x))?; - } - } - Some(result) -} - -fn parse_sysv_extended_name<'data>(digits: &[u8], names: &'data [u8]) -> Result<&'data [u8], ()> { - let offset = parse_u64_digits(digits, 10).ok_or(())?; - let offset = offset.try_into().map_err(|_| ())?; - let name_data = names.get(offset..).ok_or(())?; - let name = match memchr::memchr2(b'/', b'\0', name_data) { - Some(len) => &name_data[..len], - None => name_data, - }; - Ok(name) -} - -/// Modifies `data` to start after the extended name. -fn parse_bsd_extended_name<'data, R: ReadRef<'data>>( - digits: &[u8], - data: R, - offset: &mut u64, - size: &mut u64, -) -> Result<&'data [u8], ()> { - let len = parse_u64_digits(digits, 10).ok_or(())?; - *size = size.checked_sub(len).ok_or(())?; - let name_data = data.read_bytes(offset, len)?; - let name = match memchr::memchr(b'\0', name_data) { - Some(len) => &name_data[..len], - None => name_data, - }; - Ok(name) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn kind() { - let data = b"!\n"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Unknown); - - let data = b"\ - !\n\ - / 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu); - - let data = b"\ - !\n\ - // 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu); - - let data = b"\ - !\n\ - / 4 `\n\ - 0000\ - // 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu); - - let data = b"\ - !\n\ - /SYM64/ 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu64); - - let data = b"\ - !\n\ - /SYM64/ 4 `\n\ - 0000\ - // 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu64); - - let data = b"\ - !\n\ - __.SYMDEF 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd); - - let data = b"\ - !\n\ - #1/9 13 `\n\ - __.SYMDEF0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd); - - let data = b"\ - !\n\ - #1/16 20 `\n\ - __.SYMDEF SORTED0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd); - - let data = b"\ - !\n\ - __.SYMDEF_64 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd64); - - let data = b"\ - !\n\ - #1/12 16 `\n\ - __.SYMDEF_640000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd64); - - let data = b"\ - !\n\ - #1/19 23 `\n\ - __.SYMDEF_64 SORTED0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Bsd64); - - let data = b"\ - !\n\ - / 4 `\n\ - 0000\ - / 4 `\n\ - 0000\ - // 4 `\n\ - 0000"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Coff); - - let data = b"\ - \n\ - 0 0 \ - 0 0 \ - 0 128 \ - 6 0 \ - 0 \0\0\0\0\0\0\0\0\0\0\0\0\ - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ - \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - let archive = ArchiveFile::parse(&data[..]).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::AixBig); - } - - #[test] - fn gnu_names() { - let data = b"\ - !\n\ - // 18 `\n\ - 0123456789abcdef/\n\ - s p a c e/ 0 0 0 644 4 `\n\ - 0000\ - 0123456789abcde/0 0 0 644 3 `\n\ - odd\n\ - /0 0 0 0 644 4 `\n\ - even"; - let data = &data[..]; - let archive = ArchiveFile::parse(data).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Gnu); - let mut members = archive.members(); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"s p a c e"); - assert_eq!(member.data(data).unwrap(), &b"0000"[..]); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"0123456789abcde"); - assert_eq!(member.data(data).unwrap(), &b"odd"[..]); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"0123456789abcdef"); - assert_eq!(member.data(data).unwrap(), &b"even"[..]); - - assert!(members.next().is_none()); - } - - #[test] - fn bsd_names() { - let data = b"\ - !\n\ - 0123456789abcde 0 0 0 644 3 `\n\ - odd\n\ - #1/16 0 0 0 644 20 `\n\ - 0123456789abcdefeven"; - let data = &data[..]; - let archive = ArchiveFile::parse(data).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::Unknown); - let mut members = archive.members(); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"0123456789abcde"); - assert_eq!(member.data(data).unwrap(), &b"odd"[..]); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"0123456789abcdef"); - assert_eq!(member.data(data).unwrap(), &b"even"[..]); - - assert!(members.next().is_none()); - } - - #[test] - fn aix_names() { - let data = b"\ - \n\ - 396 0 0 \ - 128 262 0 \ - 4 262 0 \ - 1662610370 223 1 644 16 \ - 0123456789abcdef`\nord\n\ - 4 396 128 \ - 1662610374 223 1 644 16 \ - fedcba9876543210`\nrev\n\ - 94 0 262 \ - 0 0 0 0 0 \ - `\n2 128 \ - 262 0123456789abcdef\0fedcba9876543210\0"; - let data = &data[..]; - let archive = ArchiveFile::parse(data).unwrap(); - assert_eq!(archive.kind(), ArchiveKind::AixBig); - let mut members = archive.members(); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"0123456789abcdef"); - assert_eq!(member.data(data).unwrap(), &b"ord\n"[..]); - - let member = members.next().unwrap().unwrap(); - assert_eq!(member.name(), b"fedcba9876543210"); - assert_eq!(member.data(data).unwrap(), &b"rev\n"[..]); - - assert!(members.next().is_none()); - } -} diff --git a/vendor/object/src/read/coff/comdat.rs b/vendor/object/src/read/coff/comdat.rs deleted file mode 100644 index 90c29be..0000000 --- a/vendor/object/src/read/coff/comdat.rs +++ /dev/null @@ -1,211 +0,0 @@ -use core::str; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::{ - self, ComdatKind, ObjectComdat, ReadError, ReadRef, Result, SectionIndex, SymbolIndex, -}; - -use super::{CoffFile, CoffHeader, ImageSymbol}; - -/// An iterator for the COMDAT section groups in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigComdatIterator<'data, 'file, R = &'data [u8]> = - CoffComdatIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the COMDAT section groups in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffComdatIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffComdatIterator<'data, 'file, R, Coff> -{ - type Item = CoffComdat<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option { - loop { - let index = self.index; - let symbol = self.file.common.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - if let Some(comdat) = CoffComdat::parse(self.file, symbol, index) { - return Some(comdat); - } - } - } -} - -/// A COMDAT section group in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -pub type CoffBigComdat<'data, 'file, R = &'data [u8]> = - CoffComdat<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A COMDAT section group in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -#[derive(Debug)] -pub struct CoffComdat< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - file: &'file CoffFile<'data, R, Coff>, - symbol_index: SymbolIndex, - symbol: &'data Coff::ImageSymbol, - selection: u8, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffComdat<'data, 'file, R, Coff> { - fn parse( - file: &'file CoffFile<'data, R, Coff>, - section_symbol: &'data Coff::ImageSymbol, - index: usize, - ) -> Option> { - // Must be a section symbol. - if !section_symbol.has_aux_section() { - return None; - } - - // Auxiliary record must have a non-associative selection. - let aux = file.common.symbols.aux_section(index).ok()?; - let selection = aux.selection; - if selection == 0 || selection == pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE { - return None; - } - - // Find the COMDAT symbol. - let mut symbol_index = index; - let mut symbol = section_symbol; - let section_number = section_symbol.section_number(); - loop { - symbol_index += 1 + symbol.number_of_aux_symbols() as usize; - symbol = file.common.symbols.symbol(symbol_index).ok()?; - if section_number == symbol.section_number() { - break; - } - } - - Some(CoffComdat { - file, - symbol_index: SymbolIndex(symbol_index), - symbol, - selection, - }) - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffComdat<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectComdat<'data> - for CoffComdat<'data, 'file, R, Coff> -{ - type SectionIterator = CoffComdatSectionIterator<'data, 'file, R, Coff>; - - #[inline] - fn kind(&self) -> ComdatKind { - match self.selection { - pe::IMAGE_COMDAT_SELECT_NODUPLICATES => ComdatKind::NoDuplicates, - pe::IMAGE_COMDAT_SELECT_ANY => ComdatKind::Any, - pe::IMAGE_COMDAT_SELECT_SAME_SIZE => ComdatKind::SameSize, - pe::IMAGE_COMDAT_SELECT_EXACT_MATCH => ComdatKind::ExactMatch, - pe::IMAGE_COMDAT_SELECT_LARGEST => ComdatKind::Largest, - pe::IMAGE_COMDAT_SELECT_NEWEST => ComdatKind::Newest, - _ => ComdatKind::Unknown, - } - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - self.symbol_index - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - // Find the name of first symbol referring to the section. - self.symbol.name(self.file.common.symbols.strings()) - } - - #[inline] - fn name(&self) -> Result<&str> { - let bytes = self.name_bytes()?; - str::from_utf8(bytes) - .ok() - .read_error("Non UTF-8 COFF COMDAT name") - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - CoffComdatSectionIterator { - file: self.file, - section_number: self.symbol.section_number(), - index: 0, - } - } -} - -/// An iterator for the sections in a COMDAT section group in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigComdatSectionIterator<'data, 'file, R = &'data [u8]> = - CoffComdatSectionIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the sections in a COMDAT section group in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffComdatSectionIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - file: &'file CoffFile<'data, R, Coff>, - section_number: i32, - index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffComdatSectionIterator<'data, 'file, R, Coff> -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option { - // Find associated COMDAT symbols. - // TODO: it seems gcc doesn't use associated symbols for this - loop { - let index = self.index; - let symbol = self.file.common.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - - // Must be a section symbol. - if !symbol.has_aux_section() { - continue; - } - - let section_number = symbol.section_number(); - - let aux = self.file.common.symbols.aux_section(index).ok()?; - if aux.selection == pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE { - let number = if Coff::is_type_bigobj() { - u32::from(aux.number.get(LE)) | (u32::from(aux.high_number.get(LE)) << 16) - } else { - u32::from(aux.number.get(LE)) - }; - if number as i32 == self.section_number { - return Some(SectionIndex(section_number as usize)); - } - } else if aux.selection != 0 { - if section_number == self.section_number { - return Some(SectionIndex(section_number as usize)); - } - } - } - } -} diff --git a/vendor/object/src/read/coff/file.rs b/vendor/object/src/read/coff/file.rs deleted file mode 100644 index 40b9e70..0000000 --- a/vendor/object/src/read/coff/file.rs +++ /dev/null @@ -1,381 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; - -use crate::read::{ - self, Architecture, Export, FileFlags, Import, NoDynamicRelocationIterator, Object, ObjectKind, - ObjectSection, ReadError, ReadRef, Result, SectionIndex, SubArchitecture, SymbolIndex, -}; -use crate::{pe, LittleEndian as LE, Pod}; - -use super::{ - CoffComdat, CoffComdatIterator, CoffSection, CoffSectionIterator, CoffSegment, - CoffSegmentIterator, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, ImageSymbol, - SectionTable, SymbolTable, -}; - -/// The common parts of `PeFile` and `CoffFile`. -#[derive(Debug)] -pub(crate) struct CoffCommon<'data, R: ReadRef<'data>, Coff: CoffHeader = pe::ImageFileHeader> { - pub(crate) sections: SectionTable<'data>, - pub(crate) symbols: SymbolTable<'data, R, Coff>, - pub(crate) image_base: u64, -} - -/// A COFF bigobj object file with 32-bit section numbers. -/// -/// This is a file that starts with [`pe::AnonObjectHeaderBigobj`], and corresponds -/// to [`crate::FileKind::CoffBig`]. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -pub type CoffBigFile<'data, R = &'data [u8]> = CoffFile<'data, R, pe::AnonObjectHeaderBigobj>; - -/// A COFF object file. -/// -/// This is a file that starts with [`pe::ImageFileHeader`], and corresponds -/// to [`crate::FileKind::Coff`]. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct CoffFile<'data, R: ReadRef<'data> = &'data [u8], Coff: CoffHeader = pe::ImageFileHeader> -{ - pub(super) header: &'data Coff, - pub(super) common: CoffCommon<'data, R, Coff>, - pub(super) data: R, -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> CoffFile<'data, R, Coff> { - /// Parse the raw COFF file data. - pub fn parse(data: R) -> Result { - let mut offset = 0; - let header = Coff::parse(data, &mut offset)?; - let sections = header.sections(data, offset)?; - let symbols = header.symbols(data)?; - - Ok(CoffFile { - header, - common: CoffCommon { - sections, - symbols, - image_base: 0, - }, - data, - }) - } -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffFile<'data, R, Coff> -{ -} - -impl<'data, 'file, R, Coff> Object<'data, 'file> for CoffFile<'data, R, Coff> -where - 'data: 'file, - R: 'file + ReadRef<'data>, - Coff: CoffHeader, -{ - type Segment = CoffSegment<'data, 'file, R, Coff>; - type SegmentIterator = CoffSegmentIterator<'data, 'file, R, Coff>; - type Section = CoffSection<'data, 'file, R, Coff>; - type SectionIterator = CoffSectionIterator<'data, 'file, R, Coff>; - type Comdat = CoffComdat<'data, 'file, R, Coff>; - type ComdatIterator = CoffComdatIterator<'data, 'file, R, Coff>; - type Symbol = CoffSymbol<'data, 'file, R, Coff>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R, Coff>; - type SymbolTable = CoffSymbolTable<'data, 'file, R, Coff>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - fn architecture(&self) -> Architecture { - match self.header.machine() { - pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm, - pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => Architecture::Aarch64, - pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386, - pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64, - _ => Architecture::Unknown, - } - } - - fn sub_architecture(&self) -> Option { - match self.header.machine() { - pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC), - _ => None, - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - true - } - - #[inline] - fn is_64(&self) -> bool { - // Windows COFF is always 32-bit, even for 64-bit architectures. This could be confusing. - false - } - - fn kind(&self) -> ObjectKind { - ObjectKind::Relocatable - } - - fn segments(&'file self) -> CoffSegmentIterator<'data, 'file, R, Coff> { - CoffSegmentIterator { - file: self, - iter: self.common.sections.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - self.sections() - .find(|section| section.name_bytes() == Ok(section_name)) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> Result> { - let section = self.common.sections.section(index.0)?; - Ok(CoffSection { - file: self, - index, - section, - }) - } - - fn sections(&'file self) -> CoffSectionIterator<'data, 'file, R, Coff> { - CoffSectionIterator { - file: self, - iter: self.common.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> CoffComdatIterator<'data, 'file, R, Coff> { - CoffComdatIterator { - file: self, - index: 0, - } - } - - fn symbol_by_index( - &'file self, - index: SymbolIndex, - ) -> Result> { - let symbol = self.common.symbols.symbol(index.0)?; - Ok(CoffSymbol { - file: &self.common, - index, - symbol, - }) - } - - fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R, Coff> { - CoffSymbolIterator { - file: &self.common, - index: 0, - } - } - - #[inline] - fn symbol_table(&'file self) -> Option> { - Some(CoffSymbolTable { file: &self.common }) - } - - fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R, Coff> { - CoffSymbolIterator { - file: &self.common, - // Hack: don't return any. - index: self.common.symbols.len(), - } - } - - #[inline] - fn dynamic_symbol_table(&'file self) -> Option> { - None - } - - #[inline] - fn dynamic_relocations(&'file self) -> Option { - None - } - - #[inline] - fn imports(&self) -> Result>> { - // TODO: this could return undefined symbols, but not needed yet. - Ok(Vec::new()) - } - - #[inline] - fn exports(&self) -> Result>> { - // TODO: this could return global symbols, but not needed yet. - Ok(Vec::new()) - } - - fn has_debug_symbols(&self) -> bool { - self.section_by_name(".debug_info").is_some() - } - - fn relative_address_base(&self) -> u64 { - 0 - } - - #[inline] - fn entry(&self) -> u64 { - 0 - } - - fn flags(&self) -> FileFlags { - FileFlags::Coff { - characteristics: self.header.characteristics(), - } - } -} - -/// Read the `class_id` field from a [`pe::AnonObjectHeader`]. -/// -/// This can be used to determine the format of the header. -pub fn anon_object_class_id<'data, R: ReadRef<'data>>(data: R) -> Result { - let header = data - .read_at::(0) - .read_error("Invalid anon object header size or alignment")?; - Ok(header.class_id) -} - -/// A trait for generic access to [`pe::ImageFileHeader`] and [`pe::AnonObjectHeaderBigobj`]. -#[allow(missing_docs)] -pub trait CoffHeader: Debug + Pod { - type ImageSymbol: ImageSymbol; - type ImageSymbolBytes: Debug + Pod; - - /// Return true if this type is [`pe::AnonObjectHeaderBigobj`]. - /// - /// This is a property of the type, not a value in the header data. - fn is_type_bigobj() -> bool; - - fn machine(&self) -> u16; - fn number_of_sections(&self) -> u32; - fn pointer_to_symbol_table(&self) -> u32; - fn number_of_symbols(&self) -> u32; - fn characteristics(&self) -> u16; - - /// Read the file header. - /// - /// `data` must be the entire file data. - /// `offset` must be the file header offset. It is updated to point after the optional header, - /// which is where the section headers are located. - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self>; - - /// Read the section table. - /// - /// `data` must be the entire file data. - /// `offset` must be after the optional file header. - #[inline] - fn sections<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: u64, - ) -> read::Result> { - SectionTable::parse(self, data, offset) - } - - /// Read the symbol table and string table. - /// - /// `data` must be the entire file data. - #[inline] - fn symbols<'data, R: ReadRef<'data>>( - &self, - data: R, - ) -> read::Result> { - SymbolTable::parse(self, data) - } -} - -impl CoffHeader for pe::ImageFileHeader { - type ImageSymbol = pe::ImageSymbol; - type ImageSymbolBytes = pe::ImageSymbolBytes; - - fn is_type_bigobj() -> bool { - false - } - - fn machine(&self) -> u16 { - self.machine.get(LE) - } - - fn number_of_sections(&self) -> u32 { - self.number_of_sections.get(LE).into() - } - - fn pointer_to_symbol_table(&self) -> u32 { - self.pointer_to_symbol_table.get(LE) - } - - fn number_of_symbols(&self) -> u32 { - self.number_of_symbols.get(LE) - } - - fn characteristics(&self) -> u16 { - self.characteristics.get(LE) - } - - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self> { - let header = data - .read::(offset) - .read_error("Invalid COFF file header size or alignment")?; - - // Skip over the optional header. - *offset = offset - .checked_add(header.size_of_optional_header.get(LE).into()) - .read_error("Invalid COFF optional header size")?; - - // TODO: maybe validate that the machine is known? - Ok(header) - } -} - -impl CoffHeader for pe::AnonObjectHeaderBigobj { - type ImageSymbol = pe::ImageSymbolEx; - type ImageSymbolBytes = pe::ImageSymbolExBytes; - - fn is_type_bigobj() -> bool { - true - } - - fn machine(&self) -> u16 { - self.machine.get(LE) - } - - fn number_of_sections(&self) -> u32 { - self.number_of_sections.get(LE) - } - - fn pointer_to_symbol_table(&self) -> u32 { - self.pointer_to_symbol_table.get(LE) - } - - fn number_of_symbols(&self) -> u32 { - self.number_of_symbols.get(LE) - } - - fn characteristics(&self) -> u16 { - 0 - } - - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> read::Result<&'data Self> { - let header = data - .read::(offset) - .read_error("Invalid COFF bigobj file header size or alignment")?; - - if header.sig1.get(LE) != pe::IMAGE_FILE_MACHINE_UNKNOWN - || header.sig2.get(LE) != 0xffff - || header.version.get(LE) < 2 - || header.class_id != pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID - { - return Err(read::Error("Invalid COFF bigobj header values")); - } - - // TODO: maybe validate that the machine is known? - Ok(header) - } -} diff --git a/vendor/object/src/read/coff/import.rs b/vendor/object/src/read/coff/import.rs deleted file mode 100644 index a296ac3..0000000 --- a/vendor/object/src/read/coff/import.rs +++ /dev/null @@ -1,220 +0,0 @@ -//! Support for reading short import files. -//! -//! These are used by some Windows linkers as a more compact way to describe -//! dynamically imported symbols. - -use crate::read::{Architecture, Error, ReadError, ReadRef, Result}; -use crate::{pe, ByteString, Bytes, LittleEndian as LE, SubArchitecture}; - -/// A Windows short form description of a symbol to import. -/// -/// Used in Windows import libraries to provide a mapping from -/// a symbol name to a DLL export. This is not an object file. -/// -/// This is a file that starts with [`pe::ImportObjectHeader`], and corresponds -/// to [`crate::FileKind::CoffImport`]. -#[derive(Debug, Clone)] -pub struct ImportFile<'data> { - header: &'data pe::ImportObjectHeader, - kind: ImportType, - dll: ByteString<'data>, - symbol: ByteString<'data>, - import: Option>, -} - -impl<'data> ImportFile<'data> { - /// Parse it. - pub fn parse>(data: R) -> Result { - let mut offset = 0; - let header = pe::ImportObjectHeader::parse(data, &mut offset)?; - let data = header.parse_data(data, &mut offset)?; - - // Unmangles a name by removing a `?`, `@` or `_` prefix. - fn strip_prefix(s: &[u8]) -> &[u8] { - match s.split_first() { - Some((b, rest)) if [b'?', b'@', b'_'].contains(b) => rest, - _ => s, - } - } - Ok(Self { - header, - dll: data.dll, - symbol: data.symbol, - kind: match header.import_type() { - pe::IMPORT_OBJECT_CODE => ImportType::Code, - pe::IMPORT_OBJECT_DATA => ImportType::Data, - pe::IMPORT_OBJECT_CONST => ImportType::Const, - _ => return Err(Error("Invalid COFF import library import type")), - }, - import: match header.name_type() { - pe::IMPORT_OBJECT_ORDINAL => None, - pe::IMPORT_OBJECT_NAME => Some(data.symbol()), - pe::IMPORT_OBJECT_NAME_NO_PREFIX => Some(strip_prefix(data.symbol())), - pe::IMPORT_OBJECT_NAME_UNDECORATE => Some( - strip_prefix(data.symbol()) - .split(|&b| b == b'@') - .next() - .unwrap(), - ), - pe::IMPORT_OBJECT_NAME_EXPORTAS => data.export(), - _ => return Err(Error("Unknown COFF import library name type")), - } - .map(ByteString), - }) - } - - /// Get the machine type. - pub fn architecture(&self) -> Architecture { - match self.header.machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm, - pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => Architecture::Aarch64, - pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386, - pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64, - _ => Architecture::Unknown, - } - } - - /// Get the sub machine type, if available. - pub fn sub_architecture(&self) -> Option { - match self.header.machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC), - _ => None, - } - } - - /// The public symbol name. - pub fn symbol(&self) -> &'data [u8] { - self.symbol.0 - } - - /// The name of the DLL to import the symbol from. - pub fn dll(&self) -> &'data [u8] { - self.dll.0 - } - - /// The name exported from the DLL. - pub fn import(&self) -> ImportName<'data> { - match self.import { - Some(name) => ImportName::Name(name.0), - None => ImportName::Ordinal(self.header.ordinal_or_hint.get(LE)), - } - } - - /// The type of import. Usually either a function or data. - pub fn import_type(&self) -> ImportType { - self.kind - } -} - -/// The name or ordinal to import from a DLL. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ImportName<'data> { - /// Import by ordinal. Ordinarily this is a 1-based index. - Ordinal(u16), - /// Import by name. - Name(&'data [u8]), -} - -/// The kind of import symbol. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ImportType { - /// An executable code symbol. - Code, - /// A data symbol. - Data, - /// A constant value. - Const, -} - -impl pe::ImportObjectHeader { - /// Read the short import header. - /// - /// Also checks that the signature and version are valid. - /// Directly following this header will be the string data. - pub fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> { - let header = data - .read::(offset) - .read_error("Invalid COFF import library header size")?; - if header.sig1.get(LE) != 0 || header.sig2.get(LE) != pe::IMPORT_OBJECT_HDR_SIG2 { - Err(Error("Invalid COFF import library header")) - } else if header.version.get(LE) != 0 { - Err(Error("Unknown COFF import library header version")) - } else { - Ok(header) - } - } - - /// Parse the data following the header. - pub fn parse_data<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: &mut u64, - ) -> Result> { - let mut data = Bytes( - data.read_bytes(offset, u64::from(self.size_of_data.get(LE))) - .read_error("Invalid COFF import library data size")?, - ); - let symbol = data - .read_string() - .map(ByteString) - .read_error("Could not read COFF import library symbol name")?; - let dll = data - .read_string() - .map(ByteString) - .read_error("Could not read COFF import library DLL name")?; - let export = if self.name_type() == pe::IMPORT_OBJECT_NAME_EXPORTAS { - data.read_string() - .map(ByteString) - .map(Some) - .read_error("Could not read COFF import library export name")? - } else { - None - }; - Ok(ImportObjectData { - symbol, - dll, - export, - }) - } - - /// The type of import. - /// - /// This is one of the `IMPORT_OBJECT_*` constants. - pub fn import_type(&self) -> u16 { - self.name_type.get(LE) & pe::IMPORT_OBJECT_TYPE_MASK - } - - /// The type of import name. - /// - /// This is one of the `IMPORT_OBJECT_*` constants. - pub fn name_type(&self) -> u16 { - (self.name_type.get(LE) >> pe::IMPORT_OBJECT_NAME_SHIFT) & pe::IMPORT_OBJECT_NAME_MASK - } -} - -/// The data following [`pe::ImportObjectHeader`]. -#[derive(Debug, Clone)] -pub struct ImportObjectData<'data> { - symbol: ByteString<'data>, - dll: ByteString<'data>, - export: Option>, -} - -impl<'data> ImportObjectData<'data> { - /// The public symbol name. - pub fn symbol(&self) -> &'data [u8] { - self.symbol.0 - } - - /// The name of the DLL to import the symbol from. - pub fn dll(&self) -> &'data [u8] { - self.dll.0 - } - - /// The name exported from the DLL. - /// - /// This is only set if the name is not derived from the symbol name. - pub fn export(&self) -> Option<&'data [u8]> { - self.export.map(|export| export.0) - } -} diff --git a/vendor/object/src/read/coff/mod.rs b/vendor/object/src/read/coff/mod.rs deleted file mode 100644 index de397da..0000000 --- a/vendor/object/src/read/coff/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Support for reading Windows COFF files. -//! -//! Traits are used to abstract over the difference between COFF object files -//! and COFF bigobj files. The primary trait for this is [`CoffHeader`]. -//! -//! ## High level API -//! -//! [`CoffFile`] implements the [`Object`](crate::read::Object) trait for -//! COFF files. [`CoffFile`] is parameterised by [`CoffHeader`]. -//! The default parameter allows reading regular COFF object files, -//! while the type alias [`CoffBigFile`] allows reading COFF bigobj files. -//! -//! [`ImportFile`] allows reading COFF short imports that are used in import -//! libraries. Currently these are not integrated with the unified read API. -//! -//! ## Low level API -//! -//! The [`CoffHeader`] trait can be directly used to parse both COFF -//! object files (which start with [`pe::ImageFileHeader`]) and COFF bigobj -//! files (which start with [`pe::AnonObjectHeaderBigobj`]). -//! -//! ### Example for low level API -//! ```no_run -//! use object::pe; -//! use object::read::coff::{CoffHeader, ImageSymbol as _}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each section and symbol. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let mut offset = 0; -//! let header = pe::ImageFileHeader::parse(&*data, &mut offset)?; -//! let sections = header.sections(&*data, offset)?; -//! let symbols = header.symbols(&*data)?; -//! for section in sections.iter() { -//! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?)); -//! } -//! for (_index, symbol) in symbols.iter() { -//! println!("{}", String::from_utf8_lossy(symbol.name(symbols.strings())?)); -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::pe; - -mod file; -pub use file::*; - -mod section; -pub use section::*; - -mod symbol; -pub use symbol::*; - -mod relocation; -pub use relocation::*; - -mod comdat; -pub use comdat::*; - -mod import; -pub use import::*; diff --git a/vendor/object/src/read/coff/relocation.rs b/vendor/object/src/read/coff/relocation.rs deleted file mode 100644 index e990944..0000000 --- a/vendor/object/src/read/coff/relocation.rs +++ /dev/null @@ -1,106 +0,0 @@ -use alloc::fmt; -use core::slice; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::{ - ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget, SymbolIndex, -}; - -use super::{CoffFile, CoffHeader}; - -/// An iterator for the relocations in a [`CoffBigSection`](super::CoffBigSection). -pub type CoffBigRelocationIterator<'data, 'file, R = &'data [u8]> = - CoffRelocationIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the relocations in a [`CoffSection`](super::CoffSection). -pub struct CoffRelocationIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: slice::Iter<'data, pe::ImageRelocation>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffRelocationIterator<'data, 'file, R, Coff> -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - self.iter.next().map(|relocation| { - let (kind, size, addend) = match self.file.header.machine() { - pe::IMAGE_FILE_MACHINE_ARMNT => match relocation.typ.get(LE) { - pe::IMAGE_REL_ARM_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_ARM_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_ARM_REL32 => (RelocationKind::Relative, 32, -4), - pe::IMAGE_REL_ARM_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_ARM_SECREL => (RelocationKind::SectionOffset, 32, 0), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => { - match relocation.typ.get(LE) { - pe::IMAGE_REL_ARM64_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_ARM64_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_ARM64_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_ARM64_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_ARM64_ADDR64 => (RelocationKind::Absolute, 64, 0), - pe::IMAGE_REL_ARM64_REL32 => (RelocationKind::Relative, 32, -4), - typ => (RelocationKind::Coff(typ), 0, 0), - } - } - pe::IMAGE_FILE_MACHINE_I386 => match relocation.typ.get(LE) { - pe::IMAGE_REL_I386_DIR16 => (RelocationKind::Absolute, 16, 0), - pe::IMAGE_REL_I386_REL16 => (RelocationKind::Relative, 16, 0), - pe::IMAGE_REL_I386_DIR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_I386_DIR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_I386_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_I386_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_I386_SECREL7 => (RelocationKind::SectionOffset, 7, 0), - pe::IMAGE_REL_I386_REL32 => (RelocationKind::Relative, 32, -4), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - pe::IMAGE_FILE_MACHINE_AMD64 => match relocation.typ.get(LE) { - pe::IMAGE_REL_AMD64_ADDR64 => (RelocationKind::Absolute, 64, 0), - pe::IMAGE_REL_AMD64_ADDR32 => (RelocationKind::Absolute, 32, 0), - pe::IMAGE_REL_AMD64_ADDR32NB => (RelocationKind::ImageOffset, 32, 0), - pe::IMAGE_REL_AMD64_REL32 => (RelocationKind::Relative, 32, -4), - pe::IMAGE_REL_AMD64_REL32_1 => (RelocationKind::Relative, 32, -5), - pe::IMAGE_REL_AMD64_REL32_2 => (RelocationKind::Relative, 32, -6), - pe::IMAGE_REL_AMD64_REL32_3 => (RelocationKind::Relative, 32, -7), - pe::IMAGE_REL_AMD64_REL32_4 => (RelocationKind::Relative, 32, -8), - pe::IMAGE_REL_AMD64_REL32_5 => (RelocationKind::Relative, 32, -9), - pe::IMAGE_REL_AMD64_SECTION => (RelocationKind::SectionIndex, 16, 0), - pe::IMAGE_REL_AMD64_SECREL => (RelocationKind::SectionOffset, 32, 0), - pe::IMAGE_REL_AMD64_SECREL7 => (RelocationKind::SectionOffset, 7, 0), - typ => (RelocationKind::Coff(typ), 0, 0), - }, - _ => (RelocationKind::Coff(relocation.typ.get(LE)), 0, 0), - }; - let target = RelocationTarget::Symbol(SymbolIndex( - relocation.symbol_table_index.get(LE) as usize, - )); - ( - u64::from(relocation.virtual_address.get(LE)), - Relocation { - kind, - encoding: RelocationEncoding::Generic, - size, - target, - addend, - implicit_addend: true, - }, - ) - }) - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug - for CoffRelocationIterator<'data, 'file, R, Coff> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffRelocationIterator").finish() - } -} diff --git a/vendor/object/src/read/coff/section.rs b/vendor/object/src/read/coff/section.rs deleted file mode 100644 index 84a3fa9..0000000 --- a/vendor/object/src/read/coff/section.rs +++ /dev/null @@ -1,585 +0,0 @@ -use core::convert::TryFrom; -use core::{iter, result, slice, str}; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::read::util::StringTable; -use crate::read::{ - self, CompressedData, CompressedFileRange, Error, ObjectSection, ObjectSegment, ReadError, - ReadRef, Result, SectionFlags, SectionIndex, SectionKind, SegmentFlags, -}; - -use super::{CoffFile, CoffHeader, CoffRelocationIterator}; - -/// The table of section headers in a COFF or PE file. -/// -/// Returned by [`CoffHeader::sections`] and -/// [`ImageNtHeaders::sections`](crate::read::pe::ImageNtHeaders::sections). -#[derive(Debug, Default, Clone, Copy)] -pub struct SectionTable<'data> { - sections: &'data [pe::ImageSectionHeader], -} - -impl<'data> SectionTable<'data> { - /// Parse the section table. - /// - /// `data` must be the entire file data. - /// `offset` must be after the optional file header. - pub fn parse>( - header: &Coff, - data: R, - offset: u64, - ) -> Result { - let sections = data - .read_slice_at(offset, header.number_of_sections() as usize) - .read_error("Invalid COFF/PE section headers")?; - Ok(SectionTable { sections }) - } - - /// Iterate over the section headers. - /// - /// Warning: sections indices start at 1. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, pe::ImageSectionHeader> { - self.sections.iter() - } - - /// Return true if the section table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.sections.is_empty() - } - - /// The number of section headers. - #[inline] - pub fn len(&self) -> usize { - self.sections.len() - } - - /// Return the section header at the given index. - /// - /// The index is 1-based. - pub fn section(&self, index: usize) -> read::Result<&'data pe::ImageSectionHeader> { - self.sections - .get(index.wrapping_sub(1)) - .read_error("Invalid COFF/PE section index") - } - - /// Return the section header with the given name. - /// - /// The returned index is 1-based. - /// - /// Ignores sections with invalid names. - pub fn section_by_name>( - &self, - strings: StringTable<'data, R>, - name: &[u8], - ) -> Option<(usize, &'data pe::ImageSectionHeader)> { - self.sections - .iter() - .enumerate() - .find(|(_, section)| section.name(strings) == Ok(name)) - .map(|(index, section)| (index + 1, section)) - } - - /// Compute the maximum file offset used by sections. - /// - /// This will usually match the end of file, unless the PE file has a - /// [data overlay](https://security.stackexchange.com/questions/77336/how-is-the-file-overlay-read-by-an-exe-virus) - pub fn max_section_file_offset(&self) -> u64 { - let mut max = 0; - for section in self.iter() { - match (section.pointer_to_raw_data.get(LE) as u64) - .checked_add(section.size_of_raw_data.get(LE) as u64) - { - None => { - // This cannot happen, we're suming two u32 into a u64 - continue; - } - Some(end_of_section) => { - if end_of_section > max { - max = end_of_section; - } - } - } - } - max - } -} - -/// An iterator for the loadable sections in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSegmentIterator<'data, 'file, R = &'data [u8]> = - CoffSegmentIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the loadable sections in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffSegmentIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSegmentIterator<'data, 'file, R, Coff> -{ - type Item = CoffSegment<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option { - self.iter.next().map(|section| CoffSegment { - file: self.file, - section, - }) - } -} - -/// A loadable section in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -pub type CoffBigSegment<'data, 'file, R = &'data [u8]> = - CoffSegment<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A loadable section in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -#[derive(Debug)] -pub struct CoffSegment< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSegment<'data, 'file, R, Coff> { - fn bytes(&self) -> Result<&'data [u8]> { - self.section - .coff_data(self.file.data) - .read_error("Invalid COFF section offset or size") - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSegment<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSegment<'data> - for CoffSegment<'data, 'file, R, Coff> -{ - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)) - } - - #[inline] - fn size(&self) -> u64 { - u64::from(self.section.virtual_size.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.section.coff_alignment() - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - let (offset, size) = self.section.coff_file_range().unwrap_or((0, 0)); - (u64::from(offset), u64::from(size)) - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn name_bytes(&self) -> Result> { - self.section - .name(self.file.common.symbols.strings()) - .map(Some) - } - - #[inline] - fn name(&self) -> Result> { - let name = self.section.name(self.file.common.symbols.strings())?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF section name") - .map(Some) - } - - #[inline] - fn flags(&self) -> SegmentFlags { - let characteristics = self.section.characteristics.get(LE); - SegmentFlags::Coff { characteristics } - } -} - -/// An iterator for the sections in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSectionIterator<'data, 'file, R = &'data [u8]> = - CoffSectionIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the sections in a [`CoffFile`]. -#[derive(Debug)] -pub struct CoffSectionIterator< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) iter: iter::Enumerate>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSectionIterator<'data, 'file, R, Coff> -{ - type Item = CoffSection<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option { - self.iter.next().map(|(index, section)| CoffSection { - file: self.file, - index: SectionIndex(index + 1), - section, - }) - } -} - -/// A section in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -pub type CoffBigSection<'data, 'file, R = &'data [u8]> = - CoffSection<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A section in a [`CoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct CoffSection< - 'data, - 'file, - R: ReadRef<'data> = &'data [u8], - Coff: CoffHeader = pe::ImageFileHeader, -> { - pub(super) file: &'file CoffFile<'data, R, Coff>, - pub(super) index: SectionIndex, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSection<'data, 'file, R, Coff> { - fn bytes(&self) -> Result<&'data [u8]> { - self.section - .coff_data(self.file.data) - .read_error("Invalid COFF section offset or size") - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSection<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSection<'data> - for CoffSection<'data, 'file, R, Coff> -{ - type RelocationIterator = CoffRelocationIterator<'data, 'file, R, Coff>; - - #[inline] - fn index(&self) -> SectionIndex { - self.index - } - - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)) - } - - #[inline] - fn size(&self) -> u64 { - // TODO: This may need to be the length from the auxiliary symbol for this section. - u64::from(self.section.size_of_raw_data.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.section.coff_alignment() - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - let (offset, size) = self.section.coff_file_range()?; - Some((u64::from(offset), u64::from(size))) - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn compressed_file_range(&self) -> Result { - Ok(CompressedFileRange::none(self.file_range())) - } - - #[inline] - fn compressed_data(&self) -> Result> { - self.data().map(CompressedData::none) - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - self.section.name(self.file.common.symbols.strings()) - } - - #[inline] - fn name(&self) -> Result<&str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF section name") - } - - #[inline] - fn segment_name_bytes(&self) -> Result> { - Ok(None) - } - - #[inline] - fn segment_name(&self) -> Result> { - Ok(None) - } - - #[inline] - fn kind(&self) -> SectionKind { - self.section.kind() - } - - fn relocations(&self) -> CoffRelocationIterator<'data, 'file, R, Coff> { - let relocations = self.section.coff_relocations(self.file.data).unwrap_or(&[]); - CoffRelocationIterator { - file: self.file, - iter: relocations.iter(), - } - } - - fn flags(&self) -> SectionFlags { - SectionFlags::Coff { - characteristics: self.section.characteristics.get(LE), - } - } -} - -impl pe::ImageSectionHeader { - pub(crate) fn kind(&self) -> SectionKind { - let characteristics = self.characteristics.get(LE); - if characteristics & (pe::IMAGE_SCN_CNT_CODE | pe::IMAGE_SCN_MEM_EXECUTE) != 0 { - SectionKind::Text - } else if characteristics & pe::IMAGE_SCN_CNT_INITIALIZED_DATA != 0 { - if characteristics & pe::IMAGE_SCN_MEM_DISCARDABLE != 0 { - SectionKind::Other - } else if characteristics & pe::IMAGE_SCN_MEM_WRITE != 0 { - SectionKind::Data - } else { - SectionKind::ReadOnlyData - } - } else if characteristics & pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 { - SectionKind::UninitializedData - } else if characteristics & pe::IMAGE_SCN_LNK_INFO != 0 { - SectionKind::Linker - } else { - SectionKind::Unknown - } - } -} - -impl pe::ImageSectionHeader { - /// Return the string table offset of the section name. - /// - /// Returns `Ok(None)` if the name doesn't use the string table - /// and can be obtained with `raw_name` instead. - pub fn name_offset(&self) -> Result> { - let bytes = &self.name; - if bytes[0] != b'/' { - return Ok(None); - } - - if bytes[1] == b'/' { - let mut offset = 0; - for byte in bytes[2..].iter() { - let digit = match byte { - b'A'..=b'Z' => byte - b'A', - b'a'..=b'z' => byte - b'a' + 26, - b'0'..=b'9' => byte - b'0' + 52, - b'+' => 62, - b'/' => 63, - _ => return Err(Error("Invalid COFF section name base-64 offset")), - }; - offset = offset * 64 + digit as u64; - } - u32::try_from(offset) - .ok() - .read_error("Invalid COFF section name base-64 offset") - .map(Some) - } else { - let mut offset = 0; - for byte in bytes[1..].iter() { - let digit = match byte { - b'0'..=b'9' => byte - b'0', - 0 => break, - _ => return Err(Error("Invalid COFF section name base-10 offset")), - }; - offset = offset * 10 + digit as u32; - } - Ok(Some(offset)) - } - } - - /// Return the section name. - /// - /// This handles decoding names that are offsets into the symbol string table. - pub fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - if let Some(offset) = self.name_offset()? { - strings - .get(offset) - .read_error("Invalid COFF section name offset") - } else { - Ok(self.raw_name()) - } - } - - /// Return the raw section name. - pub fn raw_name(&self) -> &[u8] { - let bytes = &self.name; - match memchr::memchr(b'\0', bytes) { - Some(end) => &bytes[..end], - None => &bytes[..], - } - } - - /// Return the offset and size of the section in a COFF file. - /// - /// Returns `None` for sections that have no data in the file. - pub fn coff_file_range(&self) -> Option<(u32, u32)> { - if self.characteristics.get(LE) & pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 { - None - } else { - let offset = self.pointer_to_raw_data.get(LE); - // Note: virtual size is not used for COFF. - let size = self.size_of_raw_data.get(LE); - Some((offset, size)) - } - } - - /// Return the section data in a COFF file. - /// - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values. - pub fn coff_data<'data, R: ReadRef<'data>>(&self, data: R) -> result::Result<&'data [u8], ()> { - if let Some((offset, size)) = self.coff_file_range() { - data.read_bytes_at(offset.into(), size.into()) - } else { - Ok(&[]) - } - } - - /// Return the section alignment in bytes. - /// - /// This is only valid for sections in a COFF file. - pub fn coff_alignment(&self) -> u64 { - match self.characteristics.get(LE) & pe::IMAGE_SCN_ALIGN_MASK { - pe::IMAGE_SCN_ALIGN_1BYTES => 1, - pe::IMAGE_SCN_ALIGN_2BYTES => 2, - pe::IMAGE_SCN_ALIGN_4BYTES => 4, - pe::IMAGE_SCN_ALIGN_8BYTES => 8, - pe::IMAGE_SCN_ALIGN_16BYTES => 16, - pe::IMAGE_SCN_ALIGN_32BYTES => 32, - pe::IMAGE_SCN_ALIGN_64BYTES => 64, - pe::IMAGE_SCN_ALIGN_128BYTES => 128, - pe::IMAGE_SCN_ALIGN_256BYTES => 256, - pe::IMAGE_SCN_ALIGN_512BYTES => 512, - pe::IMAGE_SCN_ALIGN_1024BYTES => 1024, - pe::IMAGE_SCN_ALIGN_2048BYTES => 2048, - pe::IMAGE_SCN_ALIGN_4096BYTES => 4096, - pe::IMAGE_SCN_ALIGN_8192BYTES => 8192, - _ => 16, - } - } - - /// Read the relocations in a COFF file. - /// - /// `data` must be the entire file data. - pub fn coff_relocations<'data, R: ReadRef<'data>>( - &self, - data: R, - ) -> read::Result<&'data [pe::ImageRelocation]> { - let mut pointer = self.pointer_to_relocations.get(LE).into(); - let mut number: usize = self.number_of_relocations.get(LE).into(); - if number == core::u16::MAX.into() - && self.characteristics.get(LE) & pe::IMAGE_SCN_LNK_NRELOC_OVFL != 0 - { - // Extended relocations. Read first relocation (which contains extended count) & adjust - // relocations pointer. - let extended_relocation_info = data - .read_at::(pointer) - .read_error("Invalid COFF relocation offset or number")?; - number = extended_relocation_info.virtual_address.get(LE) as usize; - if number == 0 { - return Err(Error("Invalid COFF relocation number")); - } - pointer += core::mem::size_of::() as u64; - // Extended relocation info does not contribute to the count of sections. - number -= 1; - } - data.read_slice_at(pointer, number) - .read_error("Invalid COFF relocation offset or number") - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn name_offset() { - let mut section = pe::ImageSectionHeader::default(); - section.name = *b"xxxxxxxx"; - assert_eq!(section.name_offset(), Ok(None)); - section.name = *b"/0\0\0\0\0\0\0"; - assert_eq!(section.name_offset(), Ok(Some(0))); - section.name = *b"/9999999"; - assert_eq!(section.name_offset(), Ok(Some(999_9999))); - section.name = *b"//AAAAAA"; - assert_eq!(section.name_offset(), Ok(Some(0))); - section.name = *b"//D/////"; - assert_eq!(section.name_offset(), Ok(Some(0xffff_ffff))); - section.name = *b"//EAAAAA"; - assert!(section.name_offset().is_err()); - section.name = *b"////////"; - assert!(section.name_offset().is_err()); - } -} diff --git a/vendor/object/src/read/coff/symbol.rs b/vendor/object/src/read/coff/symbol.rs deleted file mode 100644 index 4f8a0c6..0000000 --- a/vendor/object/src/read/coff/symbol.rs +++ /dev/null @@ -1,635 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::convert::TryInto; -use core::fmt::Debug; -use core::str; - -use super::{CoffCommon, CoffHeader, SectionTable}; -use crate::endian::{LittleEndian as LE, U32Bytes}; -use crate::pe; -use crate::pod::{bytes_of, bytes_of_slice, Pod}; -use crate::read::util::StringTable; -use crate::read::{ - self, Bytes, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex, - SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection, -}; - -/// A table of symbol entries in a COFF or PE file. -/// -/// Also includes the string table used for the symbol names. -/// -/// Returned by [`CoffHeader::symbols`] and -/// [`ImageNtHeaders::symbols`](crate::read::pe::ImageNtHeaders::symbols). -#[derive(Debug)] -pub struct SymbolTable<'data, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - symbols: &'data [Coff::ImageSymbolBytes], - strings: StringTable<'data, R>, -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> Default for SymbolTable<'data, R, Coff> { - fn default() -> Self { - Self { - symbols: &[], - strings: StringTable::default(), - } - } -} - -impl<'data, R: ReadRef<'data>, Coff: CoffHeader> SymbolTable<'data, R, Coff> { - /// Read the symbol table. - pub fn parse(header: &Coff, data: R) -> Result { - // The symbol table may not be present. - let mut offset = header.pointer_to_symbol_table().into(); - let (symbols, strings) = if offset != 0 { - let symbols = data - .read_slice(&mut offset, header.number_of_symbols() as usize) - .read_error("Invalid COFF symbol table offset or size")?; - - // Note: don't update data when reading length; the length includes itself. - let length = data - .read_at::>(offset) - .read_error("Missing COFF string table")? - .get(LE); - let str_end = offset - .checked_add(length as u64) - .read_error("Invalid COFF string table length")?; - let strings = StringTable::new(data, offset, str_end); - - (symbols, strings) - } else { - (&[][..], StringTable::default()) - }; - - Ok(SymbolTable { symbols, strings }) - } - - /// Return the string table used for the symbol names. - #[inline] - pub fn strings(&self) -> StringTable<'data, R> { - self.strings - } - - /// Return true if the symbol table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// The number of symbol table entries. - /// - /// This includes auxiliary symbol table entries. - #[inline] - pub fn len(&self) -> usize { - self.symbols.len() - } - - /// Iterate over the symbols. - #[inline] - pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, R, Coff> { - SymbolIterator { - symbols: self, - index: 0, - } - } - - /// Return the symbol table entry at the given index. - #[inline] - pub fn symbol(&self, index: usize) -> Result<&'data Coff::ImageSymbol> { - self.get::(index, 0) - } - - /// Return the auxiliary function symbol for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - #[inline] - pub fn aux_function(&self, index: usize) -> Result<&'data pe::ImageAuxSymbolFunction> { - self.get::(index, 1) - } - - /// Return the auxiliary section symbol for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - #[inline] - pub fn aux_section(&self, index: usize) -> Result<&'data pe::ImageAuxSymbolSection> { - self.get::(index, 1) - } - - /// Return the auxiliary file name for the symbol table entry at the given index. - /// - /// Note that the index is of the symbol, not the first auxiliary record. - pub fn aux_file_name(&self, index: usize, aux_count: u8) -> Result<&'data [u8]> { - let entries = index - .checked_add(1) - .and_then(|x| Some(x..x.checked_add(aux_count.into())?)) - .and_then(|x| self.symbols.get(x)) - .read_error("Invalid COFF symbol index")?; - let bytes = bytes_of_slice(entries); - // The name is padded with nulls. - Ok(match memchr::memchr(b'\0', bytes) { - Some(end) => &bytes[..end], - None => bytes, - }) - } - - /// Return the symbol table entry or auxiliary record at the given index and offset. - pub fn get(&self, index: usize, offset: usize) -> Result<&'data T> { - let bytes = index - .checked_add(offset) - .and_then(|x| self.symbols.get(x)) - .read_error("Invalid COFF symbol index")?; - Bytes(bytes_of(bytes)) - .read() - .read_error("Invalid COFF symbol data") - } - - /// Construct a map from addresses to a user-defined map entry. - pub fn map Option>( - &self, - f: F, - ) -> SymbolMap { - let mut symbols = Vec::with_capacity(self.symbols.len()); - for (_, symbol) in self.iter() { - if !symbol.is_definition() { - continue; - } - if let Some(entry) = f(symbol) { - symbols.push(entry); - } - } - SymbolMap::new(symbols) - } -} - -/// An iterator for symbol entries in a COFF or PE file. -/// -/// Yields the index and symbol structure for each symbol. -#[derive(Debug)] -pub struct SymbolIterator<'data, 'table, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - symbols: &'table SymbolTable<'data, R, Coff>, - index: usize, -} - -impl<'data, 'table, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for SymbolIterator<'data, 'table, R, Coff> -{ - type Item = (usize, &'data Coff::ImageSymbol); - - fn next(&mut self) -> Option { - let index = self.index; - let symbol = self.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - Some((index, symbol)) - } -} - -/// A symbol table in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSymbolTable<'data, 'file, R = &'data [u8]> = - CoffSymbolTable<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A symbol table in a [`CoffFile`](super::CoffFile) -/// or [`PeFile`](crate::read::pe::PeFile). -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbolTable<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSymbolTable<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbolTable<'data> - for CoffSymbolTable<'data, 'file, R, Coff> -{ - type Symbol = CoffSymbol<'data, 'file, R, Coff>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R, Coff>; - - fn symbols(&self) -> Self::SymbolIterator { - CoffSymbolIterator { - file: self.file, - index: 0, - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> Result { - let symbol = self.file.symbols.symbol(index.0)?; - Ok(CoffSymbol { - file: self.file, - index, - symbol, - }) - } -} - -/// An iterator for the symbols in a [`CoffBigFile`](super::CoffBigFile). -pub type CoffBigSymbolIterator<'data, 'file, R = &'data [u8]> = - CoffSymbolIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// An iterator for the symbols in a [`CoffFile`](super::CoffFile) -/// or [`PeFile`](crate::read::pe::PeFile). -pub struct CoffSymbolIterator<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, - pub(crate) index: usize, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug - for CoffSymbolIterator<'data, 'file, R, Coff> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CoffSymbolIterator").finish() - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator - for CoffSymbolIterator<'data, 'file, R, Coff> -{ - type Item = CoffSymbol<'data, 'file, R, Coff>; - - fn next(&mut self) -> Option { - let index = self.index; - let symbol = self.file.symbols.symbol(index).ok()?; - self.index += 1 + symbol.number_of_aux_symbols() as usize; - Some(CoffSymbol { - file: self.file, - index: SymbolIndex(index), - symbol, - }) - } -} - -/// A symbol in a [`CoffBigFile`](super::CoffBigFile). -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -pub type CoffBigSymbol<'data, 'file, R = &'data [u8]> = - CoffSymbol<'data, 'file, R, pe::AnonObjectHeaderBigobj>; - -/// A symbol in a [`CoffFile`](super::CoffFile) or [`PeFile`](crate::read::pe::PeFile). -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Debug, Clone, Copy)] -pub struct CoffSymbol<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader> -where - R: ReadRef<'data>, - Coff: CoffHeader, -{ - pub(crate) file: &'file CoffCommon<'data, R, Coff>, - pub(crate) index: SymbolIndex, - pub(crate) symbol: &'data Coff::ImageSymbol, -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSymbol<'data, 'file, R, Coff> { - #[inline] - /// Get the raw `ImageSymbol` struct. - pub fn raw_symbol(&self) -> &'data Coff::ImageSymbol { - self.symbol - } -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed - for CoffSymbol<'data, 'file, R, Coff> -{ -} - -impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbol<'data> - for CoffSymbol<'data, 'file, R, Coff> -{ - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - fn name_bytes(&self) -> read::Result<&'data [u8]> { - if self.symbol.has_aux_file_name() { - self.file - .symbols - .aux_file_name(self.index.0, self.symbol.number_of_aux_symbols()) - } else { - self.symbol.name(self.file.symbols.strings()) - } - } - - fn name(&self) -> read::Result<&'data str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 COFF symbol name") - } - - fn address(&self) -> u64 { - // Only return an address for storage classes that we know use an address. - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC - | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL - | pe::IMAGE_SYM_CLASS_LABEL => {} - pe::IMAGE_SYM_CLASS_EXTERNAL => { - if self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED { - // Undefined or common data, neither of which have an address. - return 0; - } - } - _ => return 0, - } - self.symbol - .address(self.file.image_base, &self.file.sections) - .unwrap_or(0) - } - - fn size(&self) -> u64 { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => { - // Section symbols may duplicate the size from the section table. - if self.symbol.has_aux_section() { - if let Ok(aux) = self.file.symbols.aux_section(self.index.0) { - u64::from(aux.length.get(LE)) - } else { - 0 - } - } else { - 0 - } - } - pe::IMAGE_SYM_CLASS_EXTERNAL => { - if self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED { - // For undefined symbols, symbol.value is 0 and the size is 0. - // For common data, symbol.value is the size. - u64::from(self.symbol.value()) - } else if self.symbol.has_aux_function() { - // Function symbols may have a size. - if let Ok(aux) = self.file.symbols.aux_function(self.index.0) { - u64::from(aux.total_size.get(LE)) - } else { - 0 - } - } else { - 0 - } - } - // Most symbols don't have sizes. - _ => 0, - } - } - - fn kind(&self) -> SymbolKind { - let derived_kind = if self.symbol.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION { - SymbolKind::Text - } else { - SymbolKind::Data - }; - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => { - if self.symbol.has_aux_section() { - SymbolKind::Section - } else { - derived_kind - } - } - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => derived_kind, - pe::IMAGE_SYM_CLASS_SECTION => SymbolKind::Section, - pe::IMAGE_SYM_CLASS_FILE => SymbolKind::File, - pe::IMAGE_SYM_CLASS_LABEL => SymbolKind::Label, - _ => SymbolKind::Unknown, - } - } - - fn section(&self) -> SymbolSection { - match self.symbol.section_number() { - pe::IMAGE_SYM_UNDEFINED => { - if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL { - if self.symbol.value() == 0 { - SymbolSection::Undefined - } else { - SymbolSection::Common - } - } else if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_SECTION { - SymbolSection::Undefined - } else { - SymbolSection::Unknown - } - } - pe::IMAGE_SYM_ABSOLUTE => SymbolSection::Absolute, - pe::IMAGE_SYM_DEBUG => { - if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_FILE { - SymbolSection::None - } else { - SymbolSection::Unknown - } - } - index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)), - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value() == 0 - } - - #[inline] - fn is_definition(&self) -> bool { - self.symbol.is_definition() - } - - #[inline] - fn is_common(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL - && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED - && self.symbol.value() != 0 - } - - #[inline] - fn is_weak(&self) -> bool { - self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL - } - - #[inline] - fn scope(&self) -> SymbolScope { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => { - // TODO: determine if symbol is exported - SymbolScope::Linkage - } - _ => SymbolScope::Compilation, - } - } - - #[inline] - fn is_global(&self) -> bool { - match self.symbol.storage_class() { - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true, - _ => false, - } - } - - #[inline] - fn is_local(&self) -> bool { - !self.is_global() - } - - fn flags(&self) -> SymbolFlags { - if self.symbol.has_aux_section() { - if let Ok(aux) = self.file.symbols.aux_section(self.index.0) { - let number = if Coff::is_type_bigobj() { - u32::from(aux.number.get(LE)) | (u32::from(aux.high_number.get(LE)) << 16) - } else { - u32::from(aux.number.get(LE)) - }; - return SymbolFlags::CoffSection { - selection: aux.selection, - associative_section: if number == 0 { - None - } else { - Some(SectionIndex(number as usize)) - }, - }; - } - } - SymbolFlags::None - } -} - -/// A trait for generic access to [`pe::ImageSymbol`] and [`pe::ImageSymbolEx`]. -#[allow(missing_docs)] -pub trait ImageSymbol: Debug + Pod { - fn raw_name(&self) -> &[u8; 8]; - fn value(&self) -> u32; - fn section_number(&self) -> i32; - fn typ(&self) -> u16; - fn storage_class(&self) -> u8; - fn number_of_aux_symbols(&self) -> u8; - - /// Parse a COFF symbol name. - /// - /// `strings` must be the string table used for symbol names. - fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - let name = self.raw_name(); - if name[0] == 0 { - // If the name starts with 0 then the last 4 bytes are a string table offset. - let offset = u32::from_le_bytes(name[4..8].try_into().unwrap()); - strings - .get(offset) - .read_error("Invalid COFF symbol name offset") - } else { - // The name is inline and padded with nulls. - Ok(match memchr::memchr(b'\0', name) { - Some(end) => &name[..end], - None => &name[..], - }) - } - } - - /// Return the symbol address. - /// - /// This takes into account the image base and the section address. - fn address(&self, image_base: u64, sections: &SectionTable<'_>) -> Result { - let section_number = self.section_number() as usize; - let section = sections.section(section_number)?; - let virtual_address = u64::from(section.virtual_address.get(LE)); - let value = u64::from(self.value()); - Ok(image_base + virtual_address + value) - } - - /// Return true if the symbol is a definition of a function or data object. - fn is_definition(&self) -> bool { - if self.section_number() <= 0 { - return false; - } - match self.storage_class() { - pe::IMAGE_SYM_CLASS_STATIC => !self.has_aux_section(), - pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true, - _ => false, - } - } - - /// Return true if the symbol has an auxiliary file name. - fn has_aux_file_name(&self) -> bool { - self.number_of_aux_symbols() > 0 && self.storage_class() == pe::IMAGE_SYM_CLASS_FILE - } - - /// Return true if the symbol has an auxiliary function symbol. - fn has_aux_function(&self) -> bool { - self.number_of_aux_symbols() > 0 && self.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION - } - - /// Return true if the symbol has an auxiliary section symbol. - fn has_aux_section(&self) -> bool { - self.number_of_aux_symbols() > 0 - && self.storage_class() == pe::IMAGE_SYM_CLASS_STATIC - && self.typ() == 0 - } - - fn base_type(&self) -> u16 { - self.typ() & pe::N_BTMASK - } - - fn derived_type(&self) -> u16 { - (self.typ() & pe::N_TMASK) >> pe::N_BTSHFT - } -} - -impl ImageSymbol for pe::ImageSymbol { - fn raw_name(&self) -> &[u8; 8] { - &self.name - } - fn value(&self) -> u32 { - self.value.get(LE) - } - fn section_number(&self) -> i32 { - let section_number = self.section_number.get(LE); - if section_number >= pe::IMAGE_SYM_SECTION_MAX { - (section_number as i16) as i32 - } else { - section_number as i32 - } - } - fn typ(&self) -> u16 { - self.typ.get(LE) - } - fn storage_class(&self) -> u8 { - self.storage_class - } - fn number_of_aux_symbols(&self) -> u8 { - self.number_of_aux_symbols - } -} - -impl ImageSymbol for pe::ImageSymbolEx { - fn raw_name(&self) -> &[u8; 8] { - &self.name - } - fn value(&self) -> u32 { - self.value.get(LE) - } - fn section_number(&self) -> i32 { - self.section_number.get(LE) - } - fn typ(&self) -> u16 { - self.typ.get(LE) - } - fn storage_class(&self) -> u8 { - self.storage_class - } - fn number_of_aux_symbols(&self) -> u8 { - self.number_of_aux_symbols - } -} diff --git a/vendor/object/src/read/elf/attributes.rs b/vendor/object/src/read/elf/attributes.rs deleted file mode 100644 index bf6f35c..0000000 --- a/vendor/object/src/read/elf/attributes.rs +++ /dev/null @@ -1,307 +0,0 @@ -use core::convert::TryInto; - -use crate::elf; -use crate::endian; -use crate::read::{Bytes, Error, ReadError, Result}; - -use super::FileHeader; - -/// An ELF attributes section. -/// -/// This may be a GNU attributes section, or an architecture specific attributes section. -/// -/// An attributes section contains a series of [`AttributesSubsection`]. -/// -/// Returned by [`SectionHeader::attributes`](super::SectionHeader::attributes) -/// and [`SectionHeader::gnu_attributes`](super::SectionHeader::gnu_attributes). -#[derive(Debug, Clone)] -pub struct AttributesSection<'data, Elf: FileHeader> { - endian: Elf::Endian, - version: u8, - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> { - /// Parse an ELF attributes section given the section data. - pub fn new(endian: Elf::Endian, data: &'data [u8]) -> Result { - let mut data = Bytes(data); - - // Skip the version field that is one byte long. - let version = *data - .read::() - .read_error("Invalid ELF attributes section offset or size")?; - - Ok(AttributesSection { - endian, - version, - data, - }) - } - - /// Return the version of the attributes section. - pub fn version(&self) -> u8 { - self.version - } - - /// Return an iterator over the subsections. - pub fn subsections(&self) -> Result> { - // There is currently only one format version. - if self.version != b'A' { - return Err(Error("Unsupported ELF attributes section version")); - } - - Ok(AttributesSubsectionIterator { - endian: self.endian, - data: self.data, - }) - } -} - -/// An iterator for the subsections in an [`AttributesSection`]. -#[derive(Debug, Clone)] -pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> AttributesSubsectionIterator<'data, Elf> { - /// Return the next subsection. - pub fn next(&mut self) -> Result>> { - if self.data.is_empty() { - return Ok(None); - } - - let result = self.parse(); - if result.is_err() { - self.data = Bytes(&[]); - } - result - } - - fn parse(&mut self) -> Result>> { - // First read the subsection length. - let mut data = self.data; - let length = data - .read::>() - .read_error("ELF attributes section is too short")? - .get(self.endian); - - // Now read the entire subsection, updating self.data. - let mut data = self - .data - .read_bytes(length as usize) - .read_error("Invalid ELF attributes subsection length")?; - // Skip the subsection length field. - data.skip(4) - .read_error("Invalid ELF attributes subsection length")?; - - let vendor = data - .read_string() - .read_error("Invalid ELF attributes vendor")?; - - Ok(Some(AttributesSubsection { - endian: self.endian, - length, - vendor, - data, - })) - } -} - -/// A subsection in an [`AttributesSection`]. -/// -/// A subsection is identified by a vendor name. It contains a series of -/// [`AttributesSubsubsection`]. -#[derive(Debug, Clone)] -pub struct AttributesSubsection<'data, Elf: FileHeader> { - endian: Elf::Endian, - length: u32, - vendor: &'data [u8], - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> AttributesSubsection<'data, Elf> { - /// Return the length of the attributes subsection. - pub fn length(&self) -> u32 { - self.length - } - - /// Return the vendor name of the attributes subsection. - pub fn vendor(&self) -> &'data [u8] { - self.vendor - } - - /// Return an iterator over the sub-subsections. - pub fn subsubsections(&self) -> AttributesSubsubsectionIterator<'data, Elf> { - AttributesSubsubsectionIterator { - endian: self.endian, - data: self.data, - } - } -} - -/// An iterator for the sub-subsections in an [`AttributesSubsection`]. -#[derive(Debug, Clone)] -pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> AttributesSubsubsectionIterator<'data, Elf> { - /// Return the next sub-subsection. - pub fn next(&mut self) -> Result>> { - if self.data.is_empty() { - return Ok(None); - } - - let result = self.parse(); - if result.is_err() { - self.data = Bytes(&[]); - } - result - } - - fn parse(&mut self) -> Result>> { - // The format of a sub-section looks like this: - // - // * - // | * 0 * - // | * 0 * - let mut data = self.data; - let tag = *data - .read::() - .read_error("ELF attributes subsection is too short")?; - let length = data - .read::>() - .read_error("ELF attributes subsection is too short")? - .get(self.endian); - - // Now read the entire sub-subsection, updating self.data. - let mut data = self - .data - .read_bytes(length as usize) - .read_error("Invalid ELF attributes sub-subsection length")?; - // Skip the tag and sub-subsection size field. - data.skip(1 + 4) - .read_error("Invalid ELF attributes sub-subsection length")?; - - let indices = if tag == elf::Tag_Section || tag == elf::Tag_Symbol { - data.read_string() - .map(Bytes) - .read_error("Missing ELF attributes sub-subsection indices")? - } else if tag == elf::Tag_File { - Bytes(&[]) - } else { - return Err(Error("Unimplemented ELF attributes sub-subsection tag")); - }; - - Ok(Some(AttributesSubsubsection { - tag, - length, - indices, - data, - })) - } -} - -/// A sub-subsection in an [`AttributesSubsection`]. -/// -/// A sub-subsection is identified by a tag. It contains an optional series of indices, -/// followed by a series of attributes. -#[derive(Debug, Clone)] -pub struct AttributesSubsubsection<'data> { - tag: u8, - length: u32, - indices: Bytes<'data>, - data: Bytes<'data>, -} - -impl<'data> AttributesSubsubsection<'data> { - /// Return the tag of the attributes sub-subsection. - pub fn tag(&self) -> u8 { - self.tag - } - - /// Return the length of the attributes sub-subsection. - pub fn length(&self) -> u32 { - self.length - } - - /// Return the data containing the indices. - pub fn indices_data(&self) -> &'data [u8] { - self.indices.0 - } - - /// Return the indices. - /// - /// This will be section indices if the tag is `Tag_Section`, - /// or symbol indices if the tag is `Tag_Symbol`, - /// and otherwise it will be empty. - pub fn indices(&self) -> AttributeIndexIterator<'data> { - AttributeIndexIterator { data: self.indices } - } - - /// Return the data containing the attributes. - pub fn attributes_data(&self) -> &'data [u8] { - self.data.0 - } - - /// Return a parser for the data containing the attributes. - pub fn attributes(&self) -> AttributeReader<'data> { - AttributeReader { data: self.data } - } -} - -/// An iterator over the indices in an [`AttributesSubsubsection`]. -#[derive(Debug, Clone)] -pub struct AttributeIndexIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> AttributeIndexIterator<'data> { - /// Parse the next index. - pub fn next(&mut self) -> Result> { - if self.data.is_empty() { - return Ok(None); - } - let err = "Invalid ELF attribute index"; - self.data - .read_uleb128() - .read_error(err)? - .try_into() - .map_err(|_| ()) - .read_error(err) - .map(Some) - } -} - -/// A parser for the attributes in an [`AttributesSubsubsection`]. -/// -/// The parser relies on the caller to know the format of the data for each attribute tag. -#[derive(Debug, Clone)] -pub struct AttributeReader<'data> { - data: Bytes<'data>, -} - -impl<'data> AttributeReader<'data> { - /// Parse a tag. - pub fn read_tag(&mut self) -> Result> { - if self.data.is_empty() { - return Ok(None); - } - let err = "Invalid ELF attribute tag"; - self.data.read_uleb128().read_error(err).map(Some) - } - - /// Parse an integer value. - pub fn read_integer(&mut self) -> Result { - let err = "Invalid ELF attribute integer value"; - self.data.read_uleb128().read_error(err) - } - - /// Parse a string value. - pub fn read_string(&mut self) -> Result<&'data [u8]> { - let err = "Invalid ELF attribute string value"; - self.data.read_string().read_error(err) - } -} diff --git a/vendor/object/src/read/elf/comdat.rs b/vendor/object/src/read/elf/comdat.rs deleted file mode 100644 index 882d253..0000000 --- a/vendor/object/src/read/elf/comdat.rs +++ /dev/null @@ -1,162 +0,0 @@ -use core::fmt::Debug; -use core::{iter, slice, str}; - -use crate::elf; -use crate::endian::{Endianness, U32Bytes}; -use crate::read::{self, ComdatKind, ObjectComdat, ReadError, ReadRef, SectionIndex, SymbolIndex}; - -use super::{ElfFile, FileHeader, SectionHeader, Sym}; - -/// An iterator for the COMDAT section groups in an [`ElfFile32`](super::ElfFile32). -pub type ElfComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdatIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the COMDAT section groups in an [`ElfFile64`](super::ElfFile64). -pub type ElfComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdatIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the COMDAT section groups in an [`ElfFile`]. -#[derive(Debug)] -pub struct ElfComdatIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) iter: iter::Enumerate>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfComdatIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = ElfComdat<'data, 'file, Elf, R>; - - fn next(&mut self) -> Option { - for (_index, section) in self.iter.by_ref() { - if let Some(comdat) = ElfComdat::parse(self.file, section) { - return Some(comdat); - } - } - None - } -} - -/// A COMDAT section group in an [`ElfFile32`](super::ElfFile32). -pub type ElfComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdat<'data, 'file, elf::FileHeader32, R>; -/// A COMDAT section group in an [`ElfFile64`](super::ElfFile64). -pub type ElfComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdat<'data, 'file, elf::FileHeader64, R>; - -/// A COMDAT section group in an [`ElfFile`]. -/// -/// Most functionality is provided by the [`ObjectComdat`] trait implementation. -#[derive(Debug)] -pub struct ElfComdat<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - file: &'file ElfFile<'data, Elf, R>, - section: &'data Elf::SectionHeader, - sections: &'data [U32Bytes], -} - -impl<'data, 'file, Elf, R> ElfComdat<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - fn parse( - file: &'file ElfFile<'data, Elf, R>, - section: &'data Elf::SectionHeader, - ) -> Option> { - let (flag, sections) = section.group(file.endian, file.data).ok()??; - if flag != elf::GRP_COMDAT { - return None; - } - Some(ElfComdat { - file, - section, - sections, - }) - } -} - -impl<'data, 'file, Elf, R> read::private::Sealed for ElfComdat<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Elf, R> ObjectComdat<'data> for ElfComdat<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type SectionIterator = ElfComdatSectionIterator<'data, 'file, Elf, R>; - - #[inline] - fn kind(&self) -> ComdatKind { - ComdatKind::Any - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - SymbolIndex(self.section.sh_info(self.file.endian) as usize) - } - - fn name_bytes(&self) -> read::Result<&[u8]> { - // FIXME: check sh_link - let index = self.section.sh_info(self.file.endian) as usize; - let symbol = self.file.symbols.symbol(index)?; - symbol.name(self.file.endian, self.file.symbols.strings()) - } - - fn name(&self) -> read::Result<&str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 ELF COMDAT name") - } - - fn sections(&self) -> Self::SectionIterator { - ElfComdatSectionIterator { - file: self.file, - sections: self.sections.iter(), - } - } -} - -/// An iterator for the sections in a COMDAT section group in an [`ElfFile32`](super::ElfFile32). -pub type ElfComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdatSectionIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the sections in a COMDAT section group in an [`ElfFile64`](super::ElfFile64). -pub type ElfComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfComdatSectionIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the sections in a COMDAT section group in an [`ElfFile`]. -#[derive(Debug)] -pub struct ElfComdatSectionIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - file: &'file ElfFile<'data, Elf, R>, - sections: slice::Iter<'data, U32Bytes>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfComdatSectionIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option { - let index = self.sections.next()?; - Some(SectionIndex(index.get(self.file.endian) as usize)) - } -} diff --git a/vendor/object/src/read/elf/compression.rs b/vendor/object/src/read/elf/compression.rs deleted file mode 100644 index de2533f..0000000 --- a/vendor/object/src/read/elf/compression.rs +++ /dev/null @@ -1,56 +0,0 @@ -use core::fmt::Debug; - -use crate::elf; -use crate::endian; -use crate::pod::Pod; - -/// A trait for generic access to [`elf::CompressionHeader32`] and [`elf::CompressionHeader64`]. -#[allow(missing_docs)] -pub trait CompressionHeader: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - - fn ch_type(&self, endian: Self::Endian) -> u32; - fn ch_size(&self, endian: Self::Endian) -> Self::Word; - fn ch_addralign(&self, endian: Self::Endian) -> Self::Word; -} - -impl CompressionHeader for elf::CompressionHeader32 { - type Word = u32; - type Endian = Endian; - - #[inline] - fn ch_type(&self, endian: Self::Endian) -> u32 { - self.ch_type.get(endian) - } - - #[inline] - fn ch_size(&self, endian: Self::Endian) -> Self::Word { - self.ch_size.get(endian) - } - - #[inline] - fn ch_addralign(&self, endian: Self::Endian) -> Self::Word { - self.ch_addralign.get(endian) - } -} - -impl CompressionHeader for elf::CompressionHeader64 { - type Word = u64; - type Endian = Endian; - - #[inline] - fn ch_type(&self, endian: Self::Endian) -> u32 { - self.ch_type.get(endian) - } - - #[inline] - fn ch_size(&self, endian: Self::Endian) -> Self::Word { - self.ch_size.get(endian) - } - - #[inline] - fn ch_addralign(&self, endian: Self::Endian) -> Self::Word { - self.ch_addralign.get(endian) - } -} diff --git a/vendor/object/src/read/elf/dynamic.rs b/vendor/object/src/read/elf/dynamic.rs deleted file mode 100644 index 1661434..0000000 --- a/vendor/object/src/read/elf/dynamic.rs +++ /dev/null @@ -1,117 +0,0 @@ -use core::convert::TryInto; -use core::fmt::Debug; - -use crate::elf; -use crate::endian; -use crate::pod::Pod; -use crate::read::{ReadError, Result, StringTable}; - -/// A trait for generic access to [`elf::Dyn32`] and [`elf::Dyn64`]. -#[allow(missing_docs)] -pub trait Dyn: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - - fn d_tag(&self, endian: Self::Endian) -> Self::Word; - fn d_val(&self, endian: Self::Endian) -> Self::Word; - - /// Try to convert the tag to a `u32`. - fn tag32(&self, endian: Self::Endian) -> Option { - self.d_tag(endian).into().try_into().ok() - } - - /// Try to convert the value to a `u32`. - fn val32(&self, endian: Self::Endian) -> Option { - self.d_val(endian).into().try_into().ok() - } - - /// Return true if the value is an offset in the dynamic string table. - fn is_string(&self, endian: Self::Endian) -> bool { - if let Some(tag) = self.tag32(endian) { - match tag { - elf::DT_NEEDED - | elf::DT_SONAME - | elf::DT_RPATH - | elf::DT_RUNPATH - | elf::DT_AUXILIARY - | elf::DT_FILTER => true, - _ => false, - } - } else { - false - } - } - - /// Use the value to get a string in a string table. - /// - /// Does not check for an appropriate tag. - fn string<'data>( - &self, - endian: Self::Endian, - strings: StringTable<'data>, - ) -> Result<&'data [u8]> { - self.val32(endian) - .and_then(|val| strings.get(val).ok()) - .read_error("Invalid ELF dyn string") - } - - /// Return true if the value is an address. - fn is_address(&self, endian: Self::Endian) -> bool { - if let Some(tag) = self.tag32(endian) { - match tag { - elf::DT_PLTGOT - | elf::DT_HASH - | elf::DT_STRTAB - | elf::DT_SYMTAB - | elf::DT_RELA - | elf::DT_INIT - | elf::DT_FINI - | elf::DT_SYMBOLIC - | elf::DT_REL - | elf::DT_DEBUG - | elf::DT_JMPREL - | elf::DT_FINI_ARRAY - | elf::DT_INIT_ARRAY - | elf::DT_PREINIT_ARRAY - | elf::DT_SYMTAB_SHNDX - | elf::DT_VERDEF - | elf::DT_VERNEED - | elf::DT_VERSYM - | elf::DT_ADDRRNGLO..=elf::DT_ADDRRNGHI => true, - _ => false, - } - } else { - false - } - } -} - -impl Dyn for elf::Dyn32 { - type Word = u32; - type Endian = Endian; - - #[inline] - fn d_tag(&self, endian: Self::Endian) -> Self::Word { - self.d_tag.get(endian) - } - - #[inline] - fn d_val(&self, endian: Self::Endian) -> Self::Word { - self.d_val.get(endian) - } -} - -impl Dyn for elf::Dyn64 { - type Word = u64; - type Endian = Endian; - - #[inline] - fn d_tag(&self, endian: Self::Endian) -> Self::Word { - self.d_tag.get(endian) - } - - #[inline] - fn d_val(&self, endian: Self::Endian) -> Self::Word { - self.d_val.get(endian) - } -} diff --git a/vendor/object/src/read/elf/file.rs b/vendor/object/src/read/elf/file.rs deleted file mode 100644 index 14ba568..0000000 --- a/vendor/object/src/read/elf/file.rs +++ /dev/null @@ -1,916 +0,0 @@ -use alloc::vec::Vec; -use core::convert::TryInto; -use core::fmt::Debug; -use core::mem; - -use crate::read::{ - self, util, Architecture, ByteString, Bytes, Error, Export, FileFlags, Import, Object, - ObjectKind, ReadError, ReadRef, SectionIndex, StringTable, SymbolIndex, -}; -use crate::{elf, endian, Endian, Endianness, Pod, U32}; - -use super::{ - CompressionHeader, Dyn, ElfComdat, ElfComdatIterator, ElfDynamicRelocationIterator, ElfSection, - ElfSectionIterator, ElfSegment, ElfSegmentIterator, ElfSymbol, ElfSymbolIterator, - ElfSymbolTable, NoteHeader, ProgramHeader, Rel, Rela, RelocationSections, SectionHeader, - SectionTable, Sym, SymbolTable, -}; - -/// A 32-bit ELF object file. -/// -/// This is a file that starts with [`elf::FileHeader32`], and corresponds -/// to [`crate::FileKind::Elf32`]. -pub type ElfFile32<'data, Endian = Endianness, R = &'data [u8]> = - ElfFile<'data, elf::FileHeader32, R>; -/// A 64-bit ELF object file. -/// -/// This is a file that starts with [`elf::FileHeader64`], and corresponds -/// to [`crate::FileKind::Elf64`]. -pub type ElfFile64<'data, Endian = Endianness, R = &'data [u8]> = - ElfFile<'data, elf::FileHeader64, R>; - -/// A partially parsed ELF file. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct ElfFile<'data, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) endian: Elf::Endian, - pub(super) data: R, - pub(super) header: &'data Elf, - pub(super) segments: &'data [Elf::ProgramHeader], - pub(super) sections: SectionTable<'data, Elf, R>, - pub(super) relocations: RelocationSections, - pub(super) symbols: SymbolTable<'data, Elf, R>, - pub(super) dynamic_symbols: SymbolTable<'data, Elf, R>, -} - -impl<'data, Elf, R> ElfFile<'data, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - /// Parse the raw ELF file data. - pub fn parse(data: R) -> read::Result { - let header = Elf::parse(data)?; - let endian = header.endian()?; - let segments = header.program_headers(endian, data)?; - let sections = header.sections(endian, data)?; - let symbols = sections.symbols(endian, data, elf::SHT_SYMTAB)?; - // TODO: get dynamic symbols from DT_SYMTAB if there are no sections - let dynamic_symbols = sections.symbols(endian, data, elf::SHT_DYNSYM)?; - // The API we provide requires a mapping from section to relocations, so build it now. - let relocations = sections.relocation_sections(endian, symbols.section())?; - - Ok(ElfFile { - endian, - data, - header, - segments, - sections, - relocations, - symbols, - dynamic_symbols, - }) - } - - /// Returns the endianness. - pub fn endian(&self) -> Elf::Endian { - self.endian - } - - /// Returns the raw data. - pub fn data(&self) -> R { - self.data - } - - /// Returns the raw ELF file header. - pub fn raw_header(&self) -> &'data Elf { - self.header - } - - /// Returns the raw ELF segments. - pub fn raw_segments(&self) -> &'data [Elf::ProgramHeader] { - self.segments - } - - fn raw_section_by_name<'file>( - &'file self, - section_name: &[u8], - ) -> Option> { - self.sections - .section_by_name(self.endian, section_name) - .map(|(index, section)| ElfSection { - file: self, - index: SectionIndex(index), - section, - }) - } - - #[cfg(feature = "compression")] - fn zdebug_section_by_name<'file>( - &'file self, - section_name: &[u8], - ) -> Option> { - if !section_name.starts_with(b".debug_") { - return None; - } - let mut name = Vec::with_capacity(section_name.len() + 1); - name.extend_from_slice(b".zdebug_"); - name.extend_from_slice(§ion_name[7..]); - self.raw_section_by_name(&name) - } - - #[cfg(not(feature = "compression"))] - fn zdebug_section_by_name<'file>( - &'file self, - _section_name: &[u8], - ) -> Option> { - None - } -} - -impl<'data, Elf, R> read::private::Sealed for ElfFile<'data, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Elf, R> Object<'data, 'file> for ElfFile<'data, Elf, R> -where - 'data: 'file, - Elf: FileHeader, - R: 'file + ReadRef<'data>, -{ - type Segment = ElfSegment<'data, 'file, Elf, R>; - type SegmentIterator = ElfSegmentIterator<'data, 'file, Elf, R>; - type Section = ElfSection<'data, 'file, Elf, R>; - type SectionIterator = ElfSectionIterator<'data, 'file, Elf, R>; - type Comdat = ElfComdat<'data, 'file, Elf, R>; - type ComdatIterator = ElfComdatIterator<'data, 'file, Elf, R>; - type Symbol = ElfSymbol<'data, 'file, Elf, R>; - type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>; - type SymbolTable = ElfSymbolTable<'data, 'file, Elf, R>; - type DynamicRelocationIterator = ElfDynamicRelocationIterator<'data, 'file, Elf, R>; - - fn architecture(&self) -> Architecture { - match ( - self.header.e_machine(self.endian), - self.header.is_class_64(), - ) { - (elf::EM_AARCH64, true) => Architecture::Aarch64, - (elf::EM_AARCH64, false) => Architecture::Aarch64_Ilp32, - (elf::EM_ARM, _) => Architecture::Arm, - (elf::EM_AVR, _) => Architecture::Avr, - (elf::EM_BPF, _) => Architecture::Bpf, - (elf::EM_CSKY, _) => Architecture::Csky, - (elf::EM_386, _) => Architecture::I386, - (elf::EM_X86_64, false) => Architecture::X86_64_X32, - (elf::EM_X86_64, true) => Architecture::X86_64, - (elf::EM_HEXAGON, _) => Architecture::Hexagon, - (elf::EM_LOONGARCH, true) => Architecture::LoongArch64, - (elf::EM_MIPS, false) => Architecture::Mips, - (elf::EM_MIPS, true) => Architecture::Mips64, - (elf::EM_MSP430, _) => Architecture::Msp430, - (elf::EM_PPC, _) => Architecture::PowerPc, - (elf::EM_PPC64, _) => Architecture::PowerPc64, - (elf::EM_RISCV, false) => Architecture::Riscv32, - (elf::EM_RISCV, true) => Architecture::Riscv64, - // This is either s390 or s390x, depending on the ELF class. - // We only support the 64-bit variant s390x here. - (elf::EM_S390, true) => Architecture::S390x, - (elf::EM_SBF, _) => Architecture::Sbf, - (elf::EM_SHARC, false) => Architecture::Sharc, - (elf::EM_SPARCV9, true) => Architecture::Sparc64, - (elf::EM_XTENSA, false) => Architecture::Xtensa, - _ => Architecture::Unknown, - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - self.header.is_little_endian() - } - - #[inline] - fn is_64(&self) -> bool { - self.header.is_class_64() - } - - fn kind(&self) -> ObjectKind { - match self.header.e_type(self.endian) { - elf::ET_REL => ObjectKind::Relocatable, - elf::ET_EXEC => ObjectKind::Executable, - // TODO: check for `DF_1_PIE`? - elf::ET_DYN => ObjectKind::Dynamic, - elf::ET_CORE => ObjectKind::Core, - _ => ObjectKind::Unknown, - } - } - - fn segments(&'file self) -> ElfSegmentIterator<'data, 'file, Elf, R> { - ElfSegmentIterator { - file: self, - iter: self.segments.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - self.raw_section_by_name(section_name) - .or_else(|| self.zdebug_section_by_name(section_name)) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> read::Result> { - let section = self.sections.section(index)?; - Ok(ElfSection { - file: self, - index, - section, - }) - } - - fn sections(&'file self) -> ElfSectionIterator<'data, 'file, Elf, R> { - ElfSectionIterator { - file: self, - iter: self.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> ElfComdatIterator<'data, 'file, Elf, R> { - ElfComdatIterator { - file: self, - iter: self.sections.iter().enumerate(), - } - } - - fn symbol_by_index( - &'file self, - index: SymbolIndex, - ) -> read::Result> { - let symbol = self.symbols.symbol(index.0)?; - Ok(ElfSymbol { - endian: self.endian, - symbols: &self.symbols, - index, - symbol, - }) - } - - fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> { - ElfSymbolIterator { - endian: self.endian, - symbols: &self.symbols, - index: 0, - } - } - - fn symbol_table(&'file self) -> Option> { - if self.symbols.is_empty() { - return None; - } - Some(ElfSymbolTable { - endian: self.endian, - symbols: &self.symbols, - }) - } - - fn dynamic_symbols(&'file self) -> ElfSymbolIterator<'data, 'file, Elf, R> { - ElfSymbolIterator { - endian: self.endian, - symbols: &self.dynamic_symbols, - index: 0, - } - } - - fn dynamic_symbol_table(&'file self) -> Option> { - if self.dynamic_symbols.is_empty() { - return None; - } - Some(ElfSymbolTable { - endian: self.endian, - symbols: &self.dynamic_symbols, - }) - } - - fn dynamic_relocations( - &'file self, - ) -> Option> { - Some(ElfDynamicRelocationIterator { - section_index: SectionIndex(1), - file: self, - relocations: None, - }) - } - - fn imports(&self) -> read::Result>> { - let mut imports = Vec::new(); - for symbol in self.dynamic_symbols.iter() { - if symbol.is_undefined(self.endian) { - let name = symbol.name(self.endian, self.dynamic_symbols.strings())?; - if !name.is_empty() { - // TODO: use symbol versioning to determine library - imports.push(Import { - name: ByteString(name), - library: ByteString(&[]), - }); - } - } - } - Ok(imports) - } - - fn exports(&self) -> read::Result>> { - let mut exports = Vec::new(); - for symbol in self.dynamic_symbols.iter() { - if symbol.is_definition(self.endian) { - let name = symbol.name(self.endian, self.dynamic_symbols.strings())?; - let address = symbol.st_value(self.endian).into(); - exports.push(Export { - name: ByteString(name), - address, - }); - } - } - Ok(exports) - } - - fn has_debug_symbols(&self) -> bool { - for section in self.sections.iter() { - if let Ok(name) = self.sections.section_name(self.endian, section) { - if name == b".debug_info" || name == b".zdebug_info" { - return true; - } - } - } - false - } - - fn build_id(&self) -> read::Result> { - let endian = self.endian; - // Use section headers if present, otherwise use program headers. - if !self.sections.is_empty() { - for section in self.sections.iter() { - if let Some(mut notes) = section.notes(endian, self.data)? { - while let Some(note) = notes.next()? { - if note.name() == elf::ELF_NOTE_GNU - && note.n_type(endian) == elf::NT_GNU_BUILD_ID - { - return Ok(Some(note.desc())); - } - } - } - } - } else { - for segment in self.segments { - if let Some(mut notes) = segment.notes(endian, self.data)? { - while let Some(note) = notes.next()? { - if note.name() == elf::ELF_NOTE_GNU - && note.n_type(endian) == elf::NT_GNU_BUILD_ID - { - return Ok(Some(note.desc())); - } - } - } - } - } - Ok(None) - } - - fn gnu_debuglink(&self) -> read::Result> { - let section = match self.raw_section_by_name(b".gnu_debuglink") { - Some(section) => section, - None => return Ok(None), - }; - let data = section - .section - .data(self.endian, self.data) - .read_error("Invalid ELF .gnu_debuglink section offset or size") - .map(Bytes)?; - let filename = data - .read_string_at(0) - .read_error("Missing ELF .gnu_debuglink filename")?; - let crc_offset = util::align(filename.len() + 1, 4); - let crc = data - .read_at::>(crc_offset) - .read_error("Missing ELF .gnu_debuglink crc")? - .get(self.endian); - Ok(Some((filename, crc))) - } - - fn gnu_debugaltlink(&self) -> read::Result> { - let section = match self.raw_section_by_name(b".gnu_debugaltlink") { - Some(section) => section, - None => return Ok(None), - }; - let mut data = section - .section - .data(self.endian, self.data) - .read_error("Invalid ELF .gnu_debugaltlink section offset or size") - .map(Bytes)?; - let filename = data - .read_string() - .read_error("Missing ELF .gnu_debugaltlink filename")?; - let build_id = data.0; - Ok(Some((filename, build_id))) - } - - fn relative_address_base(&self) -> u64 { - 0 - } - - fn entry(&self) -> u64 { - self.header.e_entry(self.endian).into() - } - - fn flags(&self) -> FileFlags { - FileFlags::Elf { - os_abi: self.header.e_ident().os_abi, - abi_version: self.header.e_ident().abi_version, - e_flags: self.header.e_flags(self.endian), - } - } -} - -/// A trait for generic access to [`elf::FileHeader32`] and [`elf::FileHeader64`]. -#[allow(missing_docs)] -pub trait FileHeader: Debug + Pod { - // Ideally this would be a `u64: From`, but can't express that. - type Word: Into; - type Sword: Into; - type Endian: endian::Endian; - type ProgramHeader: ProgramHeader; - type SectionHeader: SectionHeader; - type CompressionHeader: CompressionHeader; - type NoteHeader: NoteHeader; - type Dyn: Dyn; - type Sym: Sym; - type Rel: Rel; - type Rela: Rela + From; - - /// Return true if this type is a 64-bit header. - /// - /// This is a property of the type, not a value in the header data. - fn is_type_64(&self) -> bool; - - /// Return true if this type is a 64-bit header. - /// - /// This is a property of the type, not a value in the header data. - /// - /// This is the same as [`Self::is_type_64`], but is non-dispatchable. - fn is_type_64_sized() -> bool - where - Self: Sized; - - fn e_ident(&self) -> &elf::Ident; - fn e_type(&self, endian: Self::Endian) -> u16; - fn e_machine(&self, endian: Self::Endian) -> u16; - fn e_version(&self, endian: Self::Endian) -> u32; - fn e_entry(&self, endian: Self::Endian) -> Self::Word; - fn e_phoff(&self, endian: Self::Endian) -> Self::Word; - fn e_shoff(&self, endian: Self::Endian) -> Self::Word; - fn e_flags(&self, endian: Self::Endian) -> u32; - fn e_ehsize(&self, endian: Self::Endian) -> u16; - fn e_phentsize(&self, endian: Self::Endian) -> u16; - fn e_phnum(&self, endian: Self::Endian) -> u16; - fn e_shentsize(&self, endian: Self::Endian) -> u16; - fn e_shnum(&self, endian: Self::Endian) -> u16; - fn e_shstrndx(&self, endian: Self::Endian) -> u16; - - // Provided methods. - - /// Read the file header. - /// - /// Also checks that the ident field in the file header is a supported format. - fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> { - let header = data - .read_at::(0) - .read_error("Invalid ELF header size or alignment")?; - if !header.is_supported() { - return Err(Error("Unsupported ELF header")); - } - // TODO: Check self.e_ehsize? - Ok(header) - } - - /// Check that the ident field in the file header is a supported format. - /// - /// This checks the magic number, version, class, and endianness. - fn is_supported(&self) -> bool { - let ident = self.e_ident(); - // TODO: Check self.e_version too? Requires endian though. - ident.magic == elf::ELFMAG - && (self.is_type_64() || self.is_class_32()) - && (!self.is_type_64() || self.is_class_64()) - && (self.is_little_endian() || self.is_big_endian()) - && ident.version == elf::EV_CURRENT - } - - fn is_class_32(&self) -> bool { - self.e_ident().class == elf::ELFCLASS32 - } - - fn is_class_64(&self) -> bool { - self.e_ident().class == elf::ELFCLASS64 - } - - fn is_little_endian(&self) -> bool { - self.e_ident().data == elf::ELFDATA2LSB - } - - fn is_big_endian(&self) -> bool { - self.e_ident().data == elf::ELFDATA2MSB - } - - fn endian(&self) -> read::Result { - Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported ELF endian") - } - - /// Return the first section header, if present. - /// - /// Section 0 is a special case because getting the section headers normally - /// requires `shnum`, but `shnum` may be in the first section header. - fn section_0<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result> { - let shoff: u64 = self.e_shoff(endian).into(); - if shoff == 0 { - // No section headers is ok. - return Ok(None); - } - let shentsize = usize::from(self.e_shentsize(endian)); - if shentsize != mem::size_of::() { - // Section header size must match. - return Err(Error("Invalid ELF section header entry size")); - } - data.read_at(shoff) - .map(Some) - .read_error("Invalid ELF section header offset or size") - } - - /// Return the `e_phnum` field of the header. Handles extended values. - /// - /// Returns `Err` for invalid values. - fn phnum<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result { - let e_phnum = self.e_phnum(endian); - if e_phnum < elf::PN_XNUM { - Ok(e_phnum as usize) - } else if let Some(section_0) = self.section_0(endian, data)? { - Ok(section_0.sh_info(endian) as usize) - } else { - // Section 0 must exist if e_phnum overflows. - Err(Error("Missing ELF section headers for e_phnum overflow")) - } - } - - /// Return the `e_shnum` field of the header. Handles extended values. - /// - /// Returns `Err` for invalid values. - fn shnum<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result { - let e_shnum = self.e_shnum(endian); - if e_shnum > 0 { - Ok(e_shnum as usize) - } else if let Some(section_0) = self.section_0(endian, data)? { - section_0 - .sh_size(endian) - .into() - .try_into() - .ok() - .read_error("Invalid ELF extended e_shnum") - } else { - // No section headers is ok. - Ok(0) - } - } - - /// Return the `e_shstrndx` field of the header. Handles extended values. - /// - /// Returns `Err` for invalid values (including if the index is 0). - fn shstrndx<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result { - let e_shstrndx = self.e_shstrndx(endian); - let index = if e_shstrndx != elf::SHN_XINDEX { - e_shstrndx.into() - } else if let Some(section_0) = self.section_0(endian, data)? { - section_0.sh_link(endian) - } else { - // Section 0 must exist if we're trying to read e_shstrndx. - return Err(Error("Missing ELF section headers for e_shstrndx overflow")); - }; - if index == 0 { - return Err(Error("Missing ELF e_shstrndx")); - } - Ok(index) - } - - /// Return the slice of program headers. - /// - /// Returns `Ok(&[])` if there are no program headers. - /// Returns `Err` for invalid values. - fn program_headers<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result<&'data [Self::ProgramHeader]> { - let phoff: u64 = self.e_phoff(endian).into(); - if phoff == 0 { - // No program headers is ok. - return Ok(&[]); - } - let phnum = self.phnum(endian, data)?; - if phnum == 0 { - // No program headers is ok. - return Ok(&[]); - } - let phentsize = self.e_phentsize(endian) as usize; - if phentsize != mem::size_of::() { - // Program header size must match. - return Err(Error("Invalid ELF program header entry size")); - } - data.read_slice_at(phoff, phnum) - .read_error("Invalid ELF program header size or alignment") - } - - /// Return the slice of section headers. - /// - /// Returns `Ok(&[])` if there are no section headers. - /// Returns `Err` for invalid values. - fn section_headers<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result<&'data [Self::SectionHeader]> { - let shoff: u64 = self.e_shoff(endian).into(); - if shoff == 0 { - // No section headers is ok. - return Ok(&[]); - } - let shnum = self.shnum(endian, data)?; - if shnum == 0 { - // No section headers is ok. - return Ok(&[]); - } - let shentsize = usize::from(self.e_shentsize(endian)); - if shentsize != mem::size_of::() { - // Section header size must match. - return Err(Error("Invalid ELF section header entry size")); - } - data.read_slice_at(shoff, shnum) - .read_error("Invalid ELF section header offset/size/alignment") - } - - /// Return the string table for the section headers. - fn section_strings<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - sections: &[Self::SectionHeader], - ) -> read::Result> { - if sections.is_empty() { - return Ok(StringTable::default()); - } - let index = self.shstrndx(endian, data)? as usize; - let shstrtab = sections.get(index).read_error("Invalid ELF e_shstrndx")?; - let strings = if let Some((shstrtab_offset, shstrtab_size)) = shstrtab.file_range(endian) { - let shstrtab_end = shstrtab_offset - .checked_add(shstrtab_size) - .read_error("Invalid ELF shstrtab size")?; - StringTable::new(data, shstrtab_offset, shstrtab_end) - } else { - StringTable::default() - }; - Ok(strings) - } - - /// Return the section table. - fn sections<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result> { - let sections = self.section_headers(endian, data)?; - let strings = self.section_strings(endian, data, sections)?; - Ok(SectionTable::new(sections, strings)) - } - - /// Returns whether this is a mips64el elf file. - fn is_mips64el(&self, endian: Self::Endian) -> bool { - self.is_class_64() && self.is_little_endian() && self.e_machine(endian) == elf::EM_MIPS - } -} - -impl FileHeader for elf::FileHeader32 { - type Word = u32; - type Sword = i32; - type Endian = Endian; - type ProgramHeader = elf::ProgramHeader32; - type SectionHeader = elf::SectionHeader32; - type CompressionHeader = elf::CompressionHeader32; - type NoteHeader = elf::NoteHeader32; - type Dyn = elf::Dyn32; - type Sym = elf::Sym32; - type Rel = elf::Rel32; - type Rela = elf::Rela32; - - #[inline] - fn is_type_64(&self) -> bool { - false - } - - #[inline] - fn is_type_64_sized() -> bool - where - Self: Sized, - { - false - } - - #[inline] - fn e_ident(&self) -> &elf::Ident { - &self.e_ident - } - - #[inline] - fn e_type(&self, endian: Self::Endian) -> u16 { - self.e_type.get(endian) - } - - #[inline] - fn e_machine(&self, endian: Self::Endian) -> u16 { - self.e_machine.get(endian) - } - - #[inline] - fn e_version(&self, endian: Self::Endian) -> u32 { - self.e_version.get(endian) - } - - #[inline] - fn e_entry(&self, endian: Self::Endian) -> Self::Word { - self.e_entry.get(endian) - } - - #[inline] - fn e_phoff(&self, endian: Self::Endian) -> Self::Word { - self.e_phoff.get(endian) - } - - #[inline] - fn e_shoff(&self, endian: Self::Endian) -> Self::Word { - self.e_shoff.get(endian) - } - - #[inline] - fn e_flags(&self, endian: Self::Endian) -> u32 { - self.e_flags.get(endian) - } - - #[inline] - fn e_ehsize(&self, endian: Self::Endian) -> u16 { - self.e_ehsize.get(endian) - } - - #[inline] - fn e_phentsize(&self, endian: Self::Endian) -> u16 { - self.e_phentsize.get(endian) - } - - #[inline] - fn e_phnum(&self, endian: Self::Endian) -> u16 { - self.e_phnum.get(endian) - } - - #[inline] - fn e_shentsize(&self, endian: Self::Endian) -> u16 { - self.e_shentsize.get(endian) - } - - #[inline] - fn e_shnum(&self, endian: Self::Endian) -> u16 { - self.e_shnum.get(endian) - } - - #[inline] - fn e_shstrndx(&self, endian: Self::Endian) -> u16 { - self.e_shstrndx.get(endian) - } -} - -impl FileHeader for elf::FileHeader64 { - type Word = u64; - type Sword = i64; - type Endian = Endian; - type ProgramHeader = elf::ProgramHeader64; - type SectionHeader = elf::SectionHeader64; - type CompressionHeader = elf::CompressionHeader64; - type NoteHeader = elf::NoteHeader32; - type Dyn = elf::Dyn64; - type Sym = elf::Sym64; - type Rel = elf::Rel64; - type Rela = elf::Rela64; - - #[inline] - fn is_type_64(&self) -> bool { - true - } - - #[inline] - fn is_type_64_sized() -> bool - where - Self: Sized, - { - true - } - - #[inline] - fn e_ident(&self) -> &elf::Ident { - &self.e_ident - } - - #[inline] - fn e_type(&self, endian: Self::Endian) -> u16 { - self.e_type.get(endian) - } - - #[inline] - fn e_machine(&self, endian: Self::Endian) -> u16 { - self.e_machine.get(endian) - } - - #[inline] - fn e_version(&self, endian: Self::Endian) -> u32 { - self.e_version.get(endian) - } - - #[inline] - fn e_entry(&self, endian: Self::Endian) -> Self::Word { - self.e_entry.get(endian) - } - - #[inline] - fn e_phoff(&self, endian: Self::Endian) -> Self::Word { - self.e_phoff.get(endian) - } - - #[inline] - fn e_shoff(&self, endian: Self::Endian) -> Self::Word { - self.e_shoff.get(endian) - } - - #[inline] - fn e_flags(&self, endian: Self::Endian) -> u32 { - self.e_flags.get(endian) - } - - #[inline] - fn e_ehsize(&self, endian: Self::Endian) -> u16 { - self.e_ehsize.get(endian) - } - - #[inline] - fn e_phentsize(&self, endian: Self::Endian) -> u16 { - self.e_phentsize.get(endian) - } - - #[inline] - fn e_phnum(&self, endian: Self::Endian) -> u16 { - self.e_phnum.get(endian) - } - - #[inline] - fn e_shentsize(&self, endian: Self::Endian) -> u16 { - self.e_shentsize.get(endian) - } - - #[inline] - fn e_shnum(&self, endian: Self::Endian) -> u16 { - self.e_shnum.get(endian) - } - - #[inline] - fn e_shstrndx(&self, endian: Self::Endian) -> u16 { - self.e_shstrndx.get(endian) - } -} diff --git a/vendor/object/src/read/elf/hash.rs b/vendor/object/src/read/elf/hash.rs deleted file mode 100644 index b0130cc..0000000 --- a/vendor/object/src/read/elf/hash.rs +++ /dev/null @@ -1,224 +0,0 @@ -use core::mem; - -use crate::elf; -use crate::read::{ReadError, ReadRef, Result}; -use crate::{U32, U64}; - -use super::{FileHeader, Sym, SymbolTable, Version, VersionTable}; - -/// A SysV symbol hash table in an ELF file. -/// -/// Returned by [`SectionHeader::hash`](super::SectionHeader::hash). -#[derive(Debug)] -pub struct HashTable<'data, Elf: FileHeader> { - buckets: &'data [U32], - chains: &'data [U32], -} - -impl<'data, Elf: FileHeader> HashTable<'data, Elf> { - /// Parse a SysV hash table. - /// - /// `data` should be from an [`elf::SHT_HASH`] section, or from a - /// segment pointed to via the [`elf::DT_HASH`] entry. - /// - /// The header is read at offset 0 in the given `data`. - pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result { - let mut offset = 0; - let header = data - .read::>(&mut offset) - .read_error("Invalid hash header")?; - let buckets = data - .read_slice(&mut offset, header.bucket_count.get(endian) as usize) - .read_error("Invalid hash buckets")?; - let chains = data - .read_slice(&mut offset, header.chain_count.get(endian) as usize) - .read_error("Invalid hash chains")?; - Ok(HashTable { buckets, chains }) - } - - /// Return the symbol table length. - pub fn symbol_table_length(&self) -> u32 { - self.chains.len() as u32 - } - - /// Use the hash table to find the symbol table entry with the given name, hash and version. - pub fn find>( - &self, - endian: Elf::Endian, - name: &[u8], - hash: u32, - version: Option<&Version<'_>>, - symbols: &SymbolTable<'data, Elf, R>, - versions: &VersionTable<'data, Elf>, - ) -> Option<(usize, &'data Elf::Sym)> { - // Get the chain start from the bucket for this hash. - let mut index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize; - // Avoid infinite loop. - let mut i = 0; - let strings = symbols.strings(); - while index != 0 && i < self.chains.len() { - if let Ok(symbol) = symbols.symbol(index) { - if symbol.name(endian, strings) == Ok(name) - && versions.matches(endian, index, version) - { - return Some((index, symbol)); - } - } - index = self.chains.get(index)?.get(endian) as usize; - i += 1; - } - None - } -} - -/// A GNU symbol hash table in an ELF file. -/// -/// Returned by [`SectionHeader::gnu_hash`](super::SectionHeader::gnu_hash). -#[derive(Debug)] -pub struct GnuHashTable<'data, Elf: FileHeader> { - symbol_base: u32, - bloom_shift: u32, - bloom_filters: &'data [u8], - buckets: &'data [U32], - values: &'data [U32], -} - -impl<'data, Elf: FileHeader> GnuHashTable<'data, Elf> { - /// Parse a GNU hash table. - /// - /// `data` should be from an [`elf::SHT_GNU_HASH`] section, or from a - /// segment pointed to via the [`elf::DT_GNU_HASH`] entry. - /// - /// The header is read at offset 0 in the given `data`. - /// - /// The header does not contain a length field, and so all of `data` - /// will be used as the hash table values. It does not matter if this - /// is longer than needed, and this will often the case when accessing - /// the hash table via the [`elf::DT_GNU_HASH`] entry. - pub fn parse(endian: Elf::Endian, data: &'data [u8]) -> Result { - let mut offset = 0; - let header = data - .read::>(&mut offset) - .read_error("Invalid GNU hash header")?; - let bloom_len = - u64::from(header.bloom_count.get(endian)) * mem::size_of::() as u64; - let bloom_filters = data - .read_bytes(&mut offset, bloom_len) - .read_error("Invalid GNU hash bloom filters")?; - let buckets = data - .read_slice(&mut offset, header.bucket_count.get(endian) as usize) - .read_error("Invalid GNU hash buckets")?; - let chain_count = (data.len() - offset as usize) / 4; - let values = data - .read_slice(&mut offset, chain_count) - .read_error("Invalid GNU hash values")?; - Ok(GnuHashTable { - symbol_base: header.symbol_base.get(endian), - bloom_shift: header.bloom_shift.get(endian), - bloom_filters, - buckets, - values, - }) - } - - /// Return the symbol table index of the first symbol in the hash table. - pub fn symbol_base(&self) -> u32 { - self.symbol_base - } - - /// Determine the symbol table length by finding the last entry in the hash table. - /// - /// Returns `None` if the hash table is empty or invalid. - pub fn symbol_table_length(&self, endian: Elf::Endian) -> Option { - // Ensure we find a non-empty bucket. - if self.symbol_base == 0 { - return None; - } - - // Find the highest chain index in a bucket. - let mut max_symbol = 0; - for bucket in self.buckets { - let bucket = bucket.get(endian); - if max_symbol < bucket { - max_symbol = bucket; - } - } - - // Find the end of the chain. - for value in self - .values - .get(max_symbol.checked_sub(self.symbol_base)? as usize..)? - { - max_symbol += 1; - if value.get(endian) & 1 != 0 { - return Some(max_symbol); - } - } - - None - } - - /// Use the hash table to find the symbol table entry with the given name, hash, and version. - pub fn find>( - &self, - endian: Elf::Endian, - name: &[u8], - hash: u32, - version: Option<&Version<'_>>, - symbols: &SymbolTable<'data, Elf, R>, - versions: &VersionTable<'data, Elf>, - ) -> Option<(usize, &'data Elf::Sym)> { - let word_bits = mem::size_of::() as u32 * 8; - - // Test against bloom filter. - let bloom_count = self.bloom_filters.len() / mem::size_of::(); - let offset = - ((hash / word_bits) & (bloom_count as u32 - 1)) * mem::size_of::() as u32; - let filter = if word_bits == 64 { - self.bloom_filters - .read_at::>(offset.into()) - .ok()? - .get(endian) - } else { - self.bloom_filters - .read_at::>(offset.into()) - .ok()? - .get(endian) - .into() - }; - if filter & (1 << (hash % word_bits)) == 0 { - return None; - } - if filter & (1 << ((hash >> self.bloom_shift) % word_bits)) == 0 { - return None; - } - - // Get the chain start from the bucket for this hash. - let mut index = self.buckets[(hash as usize) % self.buckets.len()].get(endian) as usize; - if index == 0 { - return None; - } - - // Test symbols in the chain. - let strings = symbols.strings(); - let symbols = symbols.symbols().get(index..)?; - let values = self - .values - .get(index.checked_sub(self.symbol_base as usize)?..)?; - for (symbol, value) in symbols.iter().zip(values.iter()) { - let value = value.get(endian); - if value | 1 == hash | 1 { - if symbol.name(endian, strings) == Ok(name) - && versions.matches(endian, index, version) - { - return Some((index, symbol)); - } - } - if value & 1 != 0 { - break; - } - index += 1; - } - None - } -} diff --git a/vendor/object/src/read/elf/mod.rs b/vendor/object/src/read/elf/mod.rs deleted file mode 100644 index 66931bd..0000000 --- a/vendor/object/src/read/elf/mod.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Support for reading ELF files. -//! -//! Traits are used to abstract over the difference between 32-bit and 64-bit ELF. -//! The primary trait for this is [`FileHeader`]. -//! -//! ## High level API -//! -//! [`ElfFile`] implements the [`Object`](crate::read::Object) trait for ELF files. -//! [`ElfFile`] is parameterised by [`FileHeader`] to allow reading both 32-bit and -//! 64-bit ELF. There are type aliases for these parameters ([`ElfFile32`] and -//! [`ElfFile64`]). -//! -//! ## Low level API -//! -//! The [`FileHeader`] trait can be directly used to parse both [`elf::FileHeader32`] -//! and [`elf::FileHeader64`]. -//! -//! ### Example for low level API -//! ```no_run -//! use object::elf; -//! use object::read::elf::{FileHeader, Sym}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each symbol. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let elf = elf::FileHeader64::::parse(&*data)?; -//! let endian = elf.endian()?; -//! let sections = elf.sections(endian, &*data)?; -//! let symbols = sections.symbols(endian, &*data, elf::SHT_SYMTAB)?; -//! for symbol in symbols.iter() { -//! let name = symbol.name(endian, symbols.strings())?; -//! println!("{}", String::from_utf8_lossy(name)); -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::elf; - -mod file; -pub use file::*; - -mod segment; -pub use segment::*; - -mod section; -pub use section::*; - -mod symbol; -pub use symbol::*; - -mod relocation; -pub use relocation::*; - -mod comdat; -pub use comdat::*; - -mod dynamic; -pub use dynamic::*; - -mod compression; -pub use compression::*; - -mod note; -pub use note::*; - -mod hash; -pub use hash::*; - -mod version; -pub use version::*; - -mod attributes; -pub use attributes::*; diff --git a/vendor/object/src/read/elf/note.rs b/vendor/object/src/read/elf/note.rs deleted file mode 100644 index e2beef9..0000000 --- a/vendor/object/src/read/elf/note.rs +++ /dev/null @@ -1,271 +0,0 @@ -use core::fmt::Debug; -use core::mem; - -use crate::elf; -use crate::endian::{self, U32}; -use crate::pod::Pod; -use crate::read::util; -use crate::read::{self, Bytes, Error, ReadError}; - -use super::FileHeader; - -/// An iterator over the notes in an ELF section or segment. -/// -/// Returned [`ProgramHeader::notes`](super::ProgramHeader::notes) -/// and [`SectionHeader::notes`](super::SectionHeader::notes). -#[derive(Debug)] -pub struct NoteIterator<'data, Elf> -where - Elf: FileHeader, -{ - endian: Elf::Endian, - align: usize, - data: Bytes<'data>, -} - -impl<'data, Elf> NoteIterator<'data, Elf> -where - Elf: FileHeader, -{ - /// An iterator over the notes in an ELF section or segment. - /// - /// `align` should be from the `p_align` field of the segment, - /// or the `sh_addralign` field of the section. Supported values are - /// either 4 or 8, but values less than 4 are treated as 4. - /// This matches the behaviour of binutils. - /// - /// Returns `Err` if `align` is invalid. - pub fn new(endian: Elf::Endian, align: Elf::Word, data: &'data [u8]) -> read::Result { - let align = match align.into() { - 0u64..=4 => 4, - 8 => 8, - _ => return Err(Error("Invalid ELF note alignment")), - }; - // TODO: check data alignment? - Ok(NoteIterator { - endian, - align, - data: Bytes(data), - }) - } - - /// Returns the next note. - pub fn next(&mut self) -> read::Result>> { - let mut data = self.data; - if data.is_empty() { - return Ok(None); - } - - let header = data - .read_at::(0) - .read_error("ELF note is too short")?; - - // The name has no alignment requirement. - let offset = mem::size_of::(); - let namesz = header.n_namesz(self.endian) as usize; - let name = data - .read_bytes_at(offset, namesz) - .read_error("Invalid ELF note namesz")? - .0; - - // The descriptor must be aligned. - let offset = util::align(offset + namesz, self.align); - let descsz = header.n_descsz(self.endian) as usize; - let desc = data - .read_bytes_at(offset, descsz) - .read_error("Invalid ELF note descsz")? - .0; - - // The next note (if any) must be aligned. - let offset = util::align(offset + descsz, self.align); - if data.skip(offset).is_err() { - data = Bytes(&[]); - } - self.data = data; - - Ok(Some(Note { header, name, desc })) - } -} - -/// A parsed [`NoteHeader`]. -#[derive(Debug)] -pub struct Note<'data, Elf> -where - Elf: FileHeader, -{ - header: &'data Elf::NoteHeader, - name: &'data [u8], - desc: &'data [u8], -} - -impl<'data, Elf: FileHeader> Note<'data, Elf> { - /// Return the `n_type` field of the `NoteHeader`. - /// - /// The meaning of this field is determined by `name`. - pub fn n_type(&self, endian: Elf::Endian) -> u32 { - self.header.n_type(endian) - } - - /// Return the `n_namesz` field of the `NoteHeader`. - pub fn n_namesz(&self, endian: Elf::Endian) -> u32 { - self.header.n_namesz(endian) - } - - /// Return the `n_descsz` field of the `NoteHeader`. - pub fn n_descsz(&self, endian: Elf::Endian) -> u32 { - self.header.n_descsz(endian) - } - - /// Return the bytes for the name field following the `NoteHeader`. - /// - /// This field is usually a string including one or more trailing null bytes - /// (but it is not required to be). - /// - /// The length of this field is given by `n_namesz`. - pub fn name_bytes(&self) -> &'data [u8] { - self.name - } - - /// Return the bytes for the name field following the `NoteHeader`, - /// excluding all trailing null bytes. - pub fn name(&self) -> &'data [u8] { - let mut name = self.name; - while let [rest @ .., 0] = name { - name = rest; - } - name - } - - /// Return the bytes for the desc field following the `NoteHeader`. - /// - /// The length of this field is given by `n_descsz`. The meaning - /// of this field is determined by `name` and `n_type`. - pub fn desc(&self) -> &'data [u8] { - self.desc - } - - /// Return an iterator for properties if this note's type is [`elf::NT_GNU_PROPERTY_TYPE_0`]. - pub fn gnu_properties( - &self, - endian: Elf::Endian, - ) -> Option> { - if self.name() != elf::ELF_NOTE_GNU || self.n_type(endian) != elf::NT_GNU_PROPERTY_TYPE_0 { - return None; - } - // Use the ELF class instead of the section alignment. - // This matches what other parsers do. - let align = if Elf::is_type_64_sized() { 8 } else { 4 }; - Some(GnuPropertyIterator { - endian, - align, - data: Bytes(self.desc), - }) - } -} - -/// A trait for generic access to [`elf::NoteHeader32`] and [`elf::NoteHeader64`]. -#[allow(missing_docs)] -pub trait NoteHeader: Debug + Pod { - type Endian: endian::Endian; - - fn n_namesz(&self, endian: Self::Endian) -> u32; - fn n_descsz(&self, endian: Self::Endian) -> u32; - fn n_type(&self, endian: Self::Endian) -> u32; -} - -impl NoteHeader for elf::NoteHeader32 { - type Endian = Endian; - - #[inline] - fn n_namesz(&self, endian: Self::Endian) -> u32 { - self.n_namesz.get(endian) - } - - #[inline] - fn n_descsz(&self, endian: Self::Endian) -> u32 { - self.n_descsz.get(endian) - } - - #[inline] - fn n_type(&self, endian: Self::Endian) -> u32 { - self.n_type.get(endian) - } -} - -impl NoteHeader for elf::NoteHeader64 { - type Endian = Endian; - - #[inline] - fn n_namesz(&self, endian: Self::Endian) -> u32 { - self.n_namesz.get(endian) - } - - #[inline] - fn n_descsz(&self, endian: Self::Endian) -> u32 { - self.n_descsz.get(endian) - } - - #[inline] - fn n_type(&self, endian: Self::Endian) -> u32 { - self.n_type.get(endian) - } -} - -/// An iterator for the properties in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note. -/// -/// Returned by [`Note::gnu_properties`]. -#[derive(Debug)] -pub struct GnuPropertyIterator<'data, Endian: endian::Endian> { - endian: Endian, - align: usize, - data: Bytes<'data>, -} - -impl<'data, Endian: endian::Endian> GnuPropertyIterator<'data, Endian> { - /// Returns the next property. - pub fn next(&mut self) -> read::Result>> { - let mut data = self.data; - if data.is_empty() { - return Ok(None); - } - - (|| -> Result<_, ()> { - let pr_type = data.read_at::>(0)?.get(self.endian); - let pr_datasz = data.read_at::>(4)?.get(self.endian) as usize; - let pr_data = data.read_bytes_at(8, pr_datasz)?.0; - data.skip(util::align(8 + pr_datasz, self.align))?; - self.data = data; - Ok(Some(GnuProperty { pr_type, pr_data })) - })() - .read_error("Invalid ELF GNU property") - } -} - -/// A property in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note. -#[derive(Debug)] -pub struct GnuProperty<'data> { - pr_type: u32, - pr_data: &'data [u8], -} - -impl<'data> GnuProperty<'data> { - /// Return the property type. - /// - /// This is one of the `GNU_PROPERTY_*` constants. - pub fn pr_type(&self) -> u32 { - self.pr_type - } - - /// Return the property data. - pub fn pr_data(&self) -> &'data [u8] { - self.pr_data - } - - /// Parse the property data as an unsigned 32-bit integer. - pub fn data_u32(&self, endian: E) -> read::Result { - Bytes(self.pr_data) - .read_at::>(0) - .read_error("Invalid ELF GNU property data") - .map(|val| val.get(endian)) - } -} diff --git a/vendor/object/src/read/elf/relocation.rs b/vendor/object/src/read/elf/relocation.rs deleted file mode 100644 index aac1574..0000000 --- a/vendor/object/src/read/elf/relocation.rs +++ /dev/null @@ -1,628 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::fmt::Debug; -use core::slice; - -use crate::elf; -use crate::endian::{self, Endianness}; -use crate::pod::Pod; -use crate::read::{ - self, Error, ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget, - SectionIndex, SymbolIndex, -}; - -use super::{ElfFile, FileHeader, SectionHeader, SectionTable}; - -/// A mapping from section index to associated relocation sections. -#[derive(Debug)] -pub struct RelocationSections { - relocations: Vec, -} - -impl RelocationSections { - /// Create a new mapping using the section table. - /// - /// Skips relocation sections that do not use the given symbol table section. - pub fn parse<'data, Elf: FileHeader, R: ReadRef<'data>>( - endian: Elf::Endian, - sections: &SectionTable<'data, Elf, R>, - symbol_section: SectionIndex, - ) -> read::Result { - let mut relocations = vec![0; sections.len()]; - for (index, section) in sections.iter().enumerate().rev() { - let sh_type = section.sh_type(endian); - if sh_type == elf::SHT_REL || sh_type == elf::SHT_RELA { - // The symbol indices used in relocations must be for the symbol table - // we are expecting to use. - let sh_link = SectionIndex(section.sh_link(endian) as usize); - if sh_link != symbol_section { - continue; - } - - let sh_info = section.sh_info(endian) as usize; - if sh_info == 0 { - // Skip dynamic relocations. - continue; - } - if sh_info >= relocations.len() { - return Err(Error("Invalid ELF sh_info for relocation section")); - } - - // Handle multiple relocation sections by chaining them. - let next = relocations[sh_info]; - relocations[sh_info] = index; - relocations[index] = next; - } - } - Ok(Self { relocations }) - } - - /// Given a section index, return the section index of the associated relocation section. - /// - /// This may also be called with a relocation section index, and it will return the - /// next associated relocation section. - pub fn get(&self, index: usize) -> Option { - self.relocations.get(index).cloned().filter(|x| *x != 0) - } -} - -pub(super) enum ElfRelaIterator<'data, Elf: FileHeader> { - Rel(slice::Iter<'data, Elf::Rel>), - Rela(slice::Iter<'data, Elf::Rela>), -} - -impl<'data, Elf: FileHeader> ElfRelaIterator<'data, Elf> { - fn is_rel(&self) -> bool { - match self { - ElfRelaIterator::Rel(_) => true, - ElfRelaIterator::Rela(_) => false, - } - } -} - -impl<'data, Elf: FileHeader> Iterator for ElfRelaIterator<'data, Elf> { - type Item = Elf::Rela; - - fn next(&mut self) -> Option { - match self { - ElfRelaIterator::Rel(ref mut i) => i.next().cloned().map(Self::Item::from), - ElfRelaIterator::Rela(ref mut i) => i.next().cloned(), - } - } -} - -/// An iterator for the dynamic relocations in an [`ElfFile32`](super::ElfFile32). -pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the dynamic relocations in an [`ElfFile64`](super::ElfFile64). -pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the dynamic relocations in an [`ElfFile`]. -pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - /// The current relocation section index. - pub(super) section_index: SectionIndex, - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) relocations: Option>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - let endian = self.file.endian; - loop { - if let Some(ref mut relocations) = self.relocations { - if let Some(reloc) = relocations.next() { - let relocation = - parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); - return Some((reloc.r_offset(endian).into(), relocation)); - } - self.relocations = None; - } - - let section = self.file.sections.section(self.section_index).ok()?; - self.section_index.0 += 1; - - let sh_link = SectionIndex(section.sh_link(endian) as usize); - if sh_link != self.file.dynamic_symbols.section() { - continue; - } - - match section.sh_type(endian) { - elf::SHT_REL => { - if let Ok(relocations) = section.data_as_array(endian, self.file.data) { - self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); - } - } - elf::SHT_RELA => { - if let Ok(relocations) = section.data_as_array(endian, self.file.data) { - self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); - } - } - _ => {} - } - } - } -} - -impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ElfDynamicRelocationIterator").finish() - } -} - -/// An iterator for the relocations for an [`ElfSection32`](super::ElfSection32). -pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the relocations for an [`ElfSection64`](super::ElfSection64). -pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the relocations for an [`ElfSection`](super::ElfSection). -pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - /// The current pointer in the chain of relocation sections. - pub(super) section_index: SectionIndex, - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) relocations: Option>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - let endian = self.file.endian; - loop { - if let Some(ref mut relocations) = self.relocations { - if let Some(reloc) = relocations.next() { - let relocation = - parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); - return Some((reloc.r_offset(endian).into(), relocation)); - } - self.relocations = None; - } - self.section_index = SectionIndex(self.file.relocations.get(self.section_index.0)?); - // The construction of RelocationSections ensures section_index is valid. - let section = self.file.sections.section(self.section_index).unwrap(); - match section.sh_type(endian) { - elf::SHT_REL => { - if let Ok(relocations) = section.data_as_array(endian, self.file.data) { - self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); - } - } - elf::SHT_RELA => { - if let Ok(relocations) = section.data_as_array(endian, self.file.data) { - self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); - } - } - _ => {} - } - } - } -} - -impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ElfSectionRelocationIterator").finish() - } -} - -fn parse_relocation( - header: &Elf, - endian: Elf::Endian, - reloc: Elf::Rela, - implicit_addend: bool, -) -> Relocation { - let mut encoding = RelocationEncoding::Generic; - let is_mips64el = header.is_mips64el(endian); - let (kind, size) = match header.e_machine(endian) { - elf::EM_AARCH64 => { - if header.is_type_64() { - match reloc.r_type(endian, false) { - elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64), - elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32), - elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16), - elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64), - elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32), - elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16), - elf::R_AARCH64_CALL26 => { - encoding = RelocationEncoding::AArch64Call; - (RelocationKind::PltRelative, 26) - } - r_type => (RelocationKind::Elf(r_type), 0), - } - } else { - match reloc.r_type(endian, false) { - elf::R_AARCH64_P32_ABS32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - } - } - } - elf::EM_ARM => match reloc.r_type(endian, false) { - elf::R_ARM_ABS32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_AVR => match reloc.r_type(endian, false) { - elf::R_AVR_32 => (RelocationKind::Absolute, 32), - elf::R_AVR_16 => (RelocationKind::Absolute, 16), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_BPF => match reloc.r_type(endian, false) { - elf::R_BPF_64_64 => (RelocationKind::Absolute, 64), - elf::R_BPF_64_32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_CSKY => match reloc.r_type(endian, false) { - elf::R_CKCORE_ADDR32 => (RelocationKind::Absolute, 32), - elf::R_CKCORE_PCREL32 => (RelocationKind::Relative, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_386 => match reloc.r_type(endian, false) { - elf::R_386_32 => (RelocationKind::Absolute, 32), - elf::R_386_PC32 => (RelocationKind::Relative, 32), - elf::R_386_GOT32 => (RelocationKind::Got, 32), - elf::R_386_PLT32 => (RelocationKind::PltRelative, 32), - elf::R_386_GOTOFF => (RelocationKind::GotBaseOffset, 32), - elf::R_386_GOTPC => (RelocationKind::GotBaseRelative, 32), - elf::R_386_16 => (RelocationKind::Absolute, 16), - elf::R_386_PC16 => (RelocationKind::Relative, 16), - elf::R_386_8 => (RelocationKind::Absolute, 8), - elf::R_386_PC8 => (RelocationKind::Relative, 8), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_X86_64 => match reloc.r_type(endian, false) { - elf::R_X86_64_64 => (RelocationKind::Absolute, 64), - elf::R_X86_64_PC32 => (RelocationKind::Relative, 32), - elf::R_X86_64_GOT32 => (RelocationKind::Got, 32), - elf::R_X86_64_PLT32 => (RelocationKind::PltRelative, 32), - elf::R_X86_64_GOTPCREL => (RelocationKind::GotRelative, 32), - elf::R_X86_64_32 => (RelocationKind::Absolute, 32), - elf::R_X86_64_32S => { - encoding = RelocationEncoding::X86Signed; - (RelocationKind::Absolute, 32) - } - elf::R_X86_64_16 => (RelocationKind::Absolute, 16), - elf::R_X86_64_PC16 => (RelocationKind::Relative, 16), - elf::R_X86_64_8 => (RelocationKind::Absolute, 8), - elf::R_X86_64_PC8 => (RelocationKind::Relative, 8), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_HEXAGON => match reloc.r_type(endian, false) { - elf::R_HEX_32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_LOONGARCH => match reloc.r_type(endian, false) { - elf::R_LARCH_32 => (RelocationKind::Absolute, 32), - elf::R_LARCH_64 => (RelocationKind::Absolute, 64), - elf::R_LARCH_32_PCREL => (RelocationKind::Relative, 32), - elf::R_LARCH_64_PCREL => (RelocationKind::Relative, 64), - elf::R_LARCH_B16 => { - encoding = RelocationEncoding::LoongArchBranch; - (RelocationKind::Relative, 16) - } - elf::R_LARCH_B21 => { - encoding = RelocationEncoding::LoongArchBranch; - (RelocationKind::Relative, 21) - } - elf::R_LARCH_B26 => { - encoding = RelocationEncoding::LoongArchBranch; - (RelocationKind::Relative, 26) - } - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) { - elf::R_MIPS_16 => (RelocationKind::Absolute, 16), - elf::R_MIPS_32 => (RelocationKind::Absolute, 32), - elf::R_MIPS_64 => (RelocationKind::Absolute, 64), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_MSP430 => match reloc.r_type(endian, false) { - elf::R_MSP430_32 => (RelocationKind::Absolute, 32), - elf::R_MSP430_16_BYTE => (RelocationKind::Absolute, 16), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_PPC => match reloc.r_type(endian, false) { - elf::R_PPC_ADDR32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_PPC64 => match reloc.r_type(endian, false) { - elf::R_PPC64_ADDR32 => (RelocationKind::Absolute, 32), - elf::R_PPC64_ADDR64 => (RelocationKind::Absolute, 64), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_RISCV => match reloc.r_type(endian, false) { - elf::R_RISCV_32 => (RelocationKind::Absolute, 32), - elf::R_RISCV_64 => (RelocationKind::Absolute, 64), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_S390 => match reloc.r_type(endian, false) { - elf::R_390_8 => (RelocationKind::Absolute, 8), - elf::R_390_16 => (RelocationKind::Absolute, 16), - elf::R_390_32 => (RelocationKind::Absolute, 32), - elf::R_390_64 => (RelocationKind::Absolute, 64), - elf::R_390_PC16 => (RelocationKind::Relative, 16), - elf::R_390_PC32 => (RelocationKind::Relative, 32), - elf::R_390_PC64 => (RelocationKind::Relative, 64), - elf::R_390_PC16DBL => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::Relative, 16) - } - elf::R_390_PC32DBL => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::Relative, 32) - } - elf::R_390_PLT16DBL => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::PltRelative, 16) - } - elf::R_390_PLT32DBL => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::PltRelative, 32) - } - elf::R_390_GOT16 => (RelocationKind::Got, 16), - elf::R_390_GOT32 => (RelocationKind::Got, 32), - elf::R_390_GOT64 => (RelocationKind::Got, 64), - elf::R_390_GOTENT => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::GotRelative, 32) - } - elf::R_390_GOTOFF16 => (RelocationKind::GotBaseOffset, 16), - elf::R_390_GOTOFF32 => (RelocationKind::GotBaseOffset, 32), - elf::R_390_GOTOFF64 => (RelocationKind::GotBaseOffset, 64), - elf::R_390_GOTPC => (RelocationKind::GotBaseRelative, 64), - elf::R_390_GOTPCDBL => { - encoding = RelocationEncoding::S390xDbl; - (RelocationKind::GotBaseRelative, 32) - } - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_SBF => match reloc.r_type(endian, false) { - elf::R_SBF_64_64 => (RelocationKind::Absolute, 64), - elf::R_SBF_64_32 => (RelocationKind::Absolute, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_SHARC => match reloc.r_type(endian, false) { - elf::R_SHARC_ADDR24_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Absolute, 24) - } - elf::R_SHARC_ADDR32_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Absolute, 32) - } - elf::R_SHARC_ADDR_VAR_V3 => { - encoding = RelocationEncoding::Generic; - (RelocationKind::Absolute, 32) - } - elf::R_SHARC_PCRSHORT_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Relative, 6) - } - elf::R_SHARC_PCRLONG_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Relative, 24) - } - elf::R_SHARC_DATA6_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Absolute, 6) - } - elf::R_SHARC_DATA16_V3 => { - encoding = RelocationEncoding::SharcTypeA; - (RelocationKind::Absolute, 16) - } - elf::R_SHARC_DATA6_VISA_V3 => { - encoding = RelocationEncoding::SharcTypeB; - (RelocationKind::Absolute, 6) - } - elf::R_SHARC_DATA7_VISA_V3 => { - encoding = RelocationEncoding::SharcTypeB; - (RelocationKind::Absolute, 7) - } - elf::R_SHARC_DATA16_VISA_V3 => { - encoding = RelocationEncoding::SharcTypeB; - (RelocationKind::Absolute, 16) - } - elf::R_SHARC_PCR6_VISA_V3 => { - encoding = RelocationEncoding::SharcTypeB; - (RelocationKind::Relative, 16) - } - elf::R_SHARC_ADDR_VAR16_V3 => { - encoding = RelocationEncoding::Generic; - (RelocationKind::Absolute, 16) - } - r_type => (RelocationKind::Elf(r_type), 0), - }, - elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => { - match reloc.r_type(endian, false) { - elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32), - elf::R_SPARC_64 | elf::R_SPARC_UA64 => (RelocationKind::Absolute, 64), - r_type => (RelocationKind::Elf(r_type), 0), - } - } - elf::EM_XTENSA => match reloc.r_type(endian, false) { - elf::R_XTENSA_32 => (RelocationKind::Absolute, 32), - elf::R_XTENSA_32_PCREL => (RelocationKind::Relative, 32), - r_type => (RelocationKind::Elf(r_type), 0), - }, - _ => (RelocationKind::Elf(reloc.r_type(endian, false)), 0), - }; - let sym = reloc.r_sym(endian, is_mips64el) as usize; - let target = if sym == 0 { - RelocationTarget::Absolute - } else { - RelocationTarget::Symbol(SymbolIndex(sym)) - }; - Relocation { - kind, - encoding, - size, - target, - addend: reloc.r_addend(endian).into(), - implicit_addend, - } -} - -/// A trait for generic access to [`elf::Rel32`] and [`elf::Rel64`]. -#[allow(missing_docs)] -pub trait Rel: Debug + Pod + Clone { - type Word: Into; - type Sword: Into; - type Endian: endian::Endian; - - fn r_offset(&self, endian: Self::Endian) -> Self::Word; - fn r_info(&self, endian: Self::Endian) -> Self::Word; - fn r_sym(&self, endian: Self::Endian) -> u32; - fn r_type(&self, endian: Self::Endian) -> u32; -} - -impl Rel for elf::Rel32 { - type Word = u32; - type Sword = i32; - type Endian = Endian; - - #[inline] - fn r_offset(&self, endian: Self::Endian) -> Self::Word { - self.r_offset.get(endian) - } - - #[inline] - fn r_info(&self, endian: Self::Endian) -> Self::Word { - self.r_info.get(endian) - } - - #[inline] - fn r_sym(&self, endian: Self::Endian) -> u32 { - self.r_sym(endian) - } - - #[inline] - fn r_type(&self, endian: Self::Endian) -> u32 { - self.r_type(endian) - } -} - -impl Rel for elf::Rel64 { - type Word = u64; - type Sword = i64; - type Endian = Endian; - - #[inline] - fn r_offset(&self, endian: Self::Endian) -> Self::Word { - self.r_offset.get(endian) - } - - #[inline] - fn r_info(&self, endian: Self::Endian) -> Self::Word { - self.r_info.get(endian) - } - - #[inline] - fn r_sym(&self, endian: Self::Endian) -> u32 { - self.r_sym(endian) - } - - #[inline] - fn r_type(&self, endian: Self::Endian) -> u32 { - self.r_type(endian) - } -} - -/// A trait for generic access to [`elf::Rela32`] and [`elf::Rela64`]. -#[allow(missing_docs)] -pub trait Rela: Debug + Pod + Clone { - type Word: Into; - type Sword: Into; - type Endian: endian::Endian; - - fn r_offset(&self, endian: Self::Endian) -> Self::Word; - fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word; - fn r_addend(&self, endian: Self::Endian) -> Self::Sword; - fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32; - fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32; -} - -impl Rela for elf::Rela32 { - type Word = u32; - type Sword = i32; - type Endian = Endian; - - #[inline] - fn r_offset(&self, endian: Self::Endian) -> Self::Word { - self.r_offset.get(endian) - } - - #[inline] - fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word { - self.r_info.get(endian) - } - - #[inline] - fn r_addend(&self, endian: Self::Endian) -> Self::Sword { - self.r_addend.get(endian) - } - - #[inline] - fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { - self.r_sym(endian) - } - - #[inline] - fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { - self.r_type(endian) - } -} - -impl Rela for elf::Rela64 { - type Word = u64; - type Sword = i64; - type Endian = Endian; - - #[inline] - fn r_offset(&self, endian: Self::Endian) -> Self::Word { - self.r_offset.get(endian) - } - - #[inline] - fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word { - self.get_r_info(endian, is_mips64el) - } - - #[inline] - fn r_addend(&self, endian: Self::Endian) -> Self::Sword { - self.r_addend.get(endian) - } - - #[inline] - fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { - self.r_sym(endian, is_mips64el) - } - - #[inline] - fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { - self.r_type(endian, is_mips64el) - } -} diff --git a/vendor/object/src/read/elf/section.rs b/vendor/object/src/read/elf/section.rs deleted file mode 100644 index 2b5ae01..0000000 --- a/vendor/object/src/read/elf/section.rs +++ /dev/null @@ -1,1150 +0,0 @@ -use core::fmt::Debug; -use core::{iter, mem, slice, str}; - -use crate::elf; -use crate::endian::{self, Endianness, U32Bytes}; -use crate::pod::Pod; -use crate::read::{ - self, Bytes, CompressedData, CompressedFileRange, CompressionFormat, Error, ObjectSection, - ReadError, ReadRef, SectionFlags, SectionIndex, SectionKind, StringTable, -}; - -use super::{ - AttributesSection, CompressionHeader, ElfFile, ElfSectionRelocationIterator, FileHeader, - GnuHashTable, HashTable, NoteIterator, RelocationSections, SymbolTable, VerdefIterator, - VerneedIterator, VersionTable, -}; - -/// The table of section headers in an ELF file. -/// -/// Also includes the string table used for the section names. -/// -/// Returned by [`FileHeader::sections`]. -#[derive(Debug, Default, Clone, Copy)] -pub struct SectionTable<'data, Elf: FileHeader, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - sections: &'data [Elf::SectionHeader], - strings: StringTable<'data, R>, -} - -impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> { - /// Create a new section table. - #[inline] - pub fn new(sections: &'data [Elf::SectionHeader], strings: StringTable<'data, R>) -> Self { - SectionTable { sections, strings } - } - - /// Iterate over the section headers. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, Elf::SectionHeader> { - self.sections.iter() - } - - /// Return true if the section table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.sections.is_empty() - } - - /// The number of section headers. - #[inline] - pub fn len(&self) -> usize { - self.sections.len() - } - - /// Return the section header at the given index. - pub fn section(&self, index: SectionIndex) -> read::Result<&'data Elf::SectionHeader> { - self.sections - .get(index.0) - .read_error("Invalid ELF section index") - } - - /// Return the section header with the given name. - /// - /// Ignores sections with invalid names. - pub fn section_by_name( - &self, - endian: Elf::Endian, - name: &[u8], - ) -> Option<(usize, &'data Elf::SectionHeader)> { - self.sections - .iter() - .enumerate() - .find(|(_, section)| self.section_name(endian, section) == Ok(name)) - } - - /// Return the section name for the given section header. - pub fn section_name( - &self, - endian: Elf::Endian, - section: &'data Elf::SectionHeader, - ) -> read::Result<&'data [u8]> { - section.name(endian, self.strings) - } - - /// Return the string table at the given section index. - /// - /// Returns an error if the section is not a string table. - #[inline] - pub fn strings( - &self, - endian: Elf::Endian, - data: R, - index: SectionIndex, - ) -> read::Result> { - self.section(index)? - .strings(endian, data)? - .read_error("Invalid ELF string section type") - } - - /// Return the symbol table of the given section type. - /// - /// Returns an empty symbol table if the symbol table does not exist. - #[inline] - pub fn symbols( - &self, - endian: Elf::Endian, - data: R, - sh_type: u32, - ) -> read::Result> { - debug_assert!(sh_type == elf::SHT_DYNSYM || sh_type == elf::SHT_SYMTAB); - - let (index, section) = match self - .iter() - .enumerate() - .find(|s| s.1.sh_type(endian) == sh_type) - { - Some(s) => s, - None => return Ok(SymbolTable::default()), - }; - - SymbolTable::parse(endian, data, self, SectionIndex(index), section) - } - - /// Return the symbol table at the given section index. - /// - /// Returns an error if the section is not a symbol table. - #[inline] - pub fn symbol_table_by_index( - &self, - endian: Elf::Endian, - data: R, - index: SectionIndex, - ) -> read::Result> { - let section = self.section(index)?; - match section.sh_type(endian) { - elf::SHT_DYNSYM | elf::SHT_SYMTAB => {} - _ => return Err(Error("Invalid ELF symbol table section type")), - } - SymbolTable::parse(endian, data, self, index, section) - } - - /// Create a mapping from section index to associated relocation sections. - #[inline] - pub fn relocation_sections( - &self, - endian: Elf::Endian, - symbol_section: SectionIndex, - ) -> read::Result { - RelocationSections::parse(endian, self, symbol_section) - } - - /// Return the contents of a dynamic section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if there is no `SHT_DYNAMIC` section. - /// Returns `Err` for invalid values. - pub fn dynamic( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result> { - for section in self.sections { - if let Some(dynamic) = section.dynamic(endian, data)? { - return Ok(Some(dynamic)); - } - } - Ok(None) - } - - /// Return the header of a SysV hash section. - /// - /// Returns `Ok(None)` if there is no SysV GNU hash section. - /// Returns `Err` for invalid values. - pub fn hash_header( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result>> { - for section in self.sections { - if let Some(hash) = section.hash_header(endian, data)? { - return Ok(Some(hash)); - } - } - Ok(None) - } - - /// Return the contents of a SysV hash section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if there is no SysV hash section. - /// Returns `Err` for invalid values. - pub fn hash( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - for section in self.sections { - if let Some(hash) = section.hash(endian, data)? { - return Ok(Some(hash)); - } - } - Ok(None) - } - - /// Return the header of a GNU hash section. - /// - /// Returns `Ok(None)` if there is no GNU hash section. - /// Returns `Err` for invalid values. - pub fn gnu_hash_header( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result>> { - for section in self.sections { - if let Some(hash) = section.gnu_hash_header(endian, data)? { - return Ok(Some(hash)); - } - } - Ok(None) - } - - /// Return the contents of a GNU hash section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if there is no GNU hash section. - /// Returns `Err` for invalid values. - pub fn gnu_hash( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - for section in self.sections { - if let Some(hash) = section.gnu_hash(endian, data)? { - return Ok(Some(hash)); - } - } - Ok(None) - } - - /// Return the contents of a `SHT_GNU_VERSYM` section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if there is no `SHT_GNU_VERSYM` section. - /// Returns `Err` for invalid values. - pub fn gnu_versym( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result], SectionIndex)>> { - for section in self.sections { - if let Some(syms) = section.gnu_versym(endian, data)? { - return Ok(Some(syms)); - } - } - Ok(None) - } - - /// Return the contents of a `SHT_GNU_VERDEF` section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if there is no `SHT_GNU_VERDEF` section. - /// Returns `Err` for invalid values. - pub fn gnu_verdef( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - for section in self.sections { - if let Some(defs) = section.gnu_verdef(endian, data)? { - return Ok(Some(defs)); - } - } - Ok(None) - } - - /// Return the contents of a `SHT_GNU_VERNEED` section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if there is no `SHT_GNU_VERNEED` section. - /// Returns `Err` for invalid values. - pub fn gnu_verneed( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - for section in self.sections { - if let Some(needs) = section.gnu_verneed(endian, data)? { - return Ok(Some(needs)); - } - } - Ok(None) - } - - /// Returns the symbol version table. - /// - /// Returns `Ok(None)` if there is no `SHT_GNU_VERSYM` section. - /// Returns `Err` for invalid values. - pub fn versions( - &self, - endian: Elf::Endian, - data: R, - ) -> read::Result>> { - let (versyms, link) = match self.gnu_versym(endian, data)? { - Some(val) => val, - None => return Ok(None), - }; - let strings = self.symbol_table_by_index(endian, data, link)?.strings(); - // TODO: check links? - let verdefs = self.gnu_verdef(endian, data)?.map(|x| x.0); - let verneeds = self.gnu_verneed(endian, data)?.map(|x| x.0); - VersionTable::parse(endian, versyms, verdefs, verneeds, strings).map(Some) - } -} - -/// An iterator for the sections in an [`ElfFile32`](super::ElfFile32). -pub type ElfSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSectionIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the sections in an [`ElfFile64`](super::ElfFile64). -pub type ElfSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSectionIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the sections in an [`ElfFile`]. -#[derive(Debug)] -pub struct ElfSectionIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) iter: iter::Enumerate>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfSectionIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = ElfSection<'data, 'file, Elf, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|(index, section)| ElfSection { - index: SectionIndex(index), - file: self.file, - section, - }) - } -} - -/// A section in an [`ElfFile32`](super::ElfFile32). -pub type ElfSection32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSection<'data, 'file, elf::FileHeader32, R>; -/// A section in an [`ElfFile64`](super::ElfFile64). -pub type ElfSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSection<'data, 'file, elf::FileHeader64, R>; - -/// A section in an [`ElfFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct ElfSection<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) index: SectionIndex, - pub(super) section: &'data Elf::SectionHeader, -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, Elf, R> { - fn bytes(&self) -> read::Result<&'data [u8]> { - self.section - .data(self.file.endian, self.file.data) - .read_error("Invalid ELF section size or offset") - } - - fn maybe_compressed(&self) -> read::Result> { - let endian = self.file.endian; - if let Some((header, offset, compressed_size)) = - self.section.compression(endian, self.file.data)? - { - let format = match header.ch_type(endian) { - elf::ELFCOMPRESS_ZLIB => CompressionFormat::Zlib, - elf::ELFCOMPRESS_ZSTD => CompressionFormat::Zstandard, - _ => return Err(Error("Unsupported ELF compression type")), - }; - let uncompressed_size = header.ch_size(endian).into(); - Ok(Some(CompressedFileRange { - format, - offset, - compressed_size, - uncompressed_size, - })) - } else { - Ok(None) - } - } - - /// Try GNU-style "ZLIB" header decompression. - fn maybe_compressed_gnu(&self) -> read::Result> { - let name = match self.name() { - Ok(name) => name, - // I think it's ok to ignore this error? - Err(_) => return Ok(None), - }; - if !name.starts_with(".zdebug_") { - return Ok(None); - } - let (section_offset, section_size) = self - .section - .file_range(self.file.endian) - .read_error("Invalid ELF GNU compressed section type")?; - let mut offset = section_offset; - let data = self.file.data; - // Assume ZLIB-style uncompressed data is no more than 4GB to avoid accidentally - // huge allocations. This also reduces the chance of accidentally matching on a - // .debug_str that happens to start with "ZLIB". - if data - .read_bytes(&mut offset, 8) - .read_error("ELF GNU compressed section is too short")? - != b"ZLIB\0\0\0\0" - { - return Err(Error("Invalid ELF GNU compressed section header")); - } - let uncompressed_size = data - .read::>(&mut offset) - .read_error("ELF GNU compressed section is too short")? - .get(endian::BigEndian) - .into(); - let compressed_size = section_size - .checked_sub(offset - section_offset) - .read_error("ELF GNU compressed section is too short")?; - Ok(Some(CompressedFileRange { - format: CompressionFormat::Zlib, - offset, - compressed_size, - uncompressed_size, - })) - } -} - -impl<'data, 'file, Elf, R> read::private::Sealed for ElfSection<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Elf, R> ObjectSection<'data> for ElfSection<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type RelocationIterator = ElfSectionRelocationIterator<'data, 'file, Elf, R>; - - #[inline] - fn index(&self) -> SectionIndex { - self.index - } - - #[inline] - fn address(&self) -> u64 { - self.section.sh_addr(self.file.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - self.section.sh_size(self.file.endian).into() - } - - #[inline] - fn align(&self) -> u64 { - self.section.sh_addralign(self.file.endian).into() - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - self.section.file_range(self.file.endian) - } - - #[inline] - fn data(&self) -> read::Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> read::Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - fn compressed_file_range(&self) -> read::Result { - Ok(if let Some(data) = self.maybe_compressed()? { - data - } else if let Some(data) = self.maybe_compressed_gnu()? { - data - } else { - CompressedFileRange::none(self.file_range()) - }) - } - - fn compressed_data(&self) -> read::Result> { - self.compressed_file_range()?.data(self.file.data) - } - - fn name_bytes(&self) -> read::Result<&[u8]> { - self.file - .sections - .section_name(self.file.endian, self.section) - } - - fn name(&self) -> read::Result<&str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 ELF section name") - } - - #[inline] - fn segment_name_bytes(&self) -> read::Result> { - Ok(None) - } - - #[inline] - fn segment_name(&self) -> read::Result> { - Ok(None) - } - - fn kind(&self) -> SectionKind { - let flags = self.section.sh_flags(self.file.endian).into(); - let sh_type = self.section.sh_type(self.file.endian); - match sh_type { - elf::SHT_PROGBITS => { - if flags & u64::from(elf::SHF_ALLOC) != 0 { - if flags & u64::from(elf::SHF_EXECINSTR) != 0 { - SectionKind::Text - } else if flags & u64::from(elf::SHF_TLS) != 0 { - SectionKind::Tls - } else if flags & u64::from(elf::SHF_WRITE) != 0 { - SectionKind::Data - } else if flags & u64::from(elf::SHF_STRINGS) != 0 { - SectionKind::ReadOnlyString - } else { - SectionKind::ReadOnlyData - } - } else if flags & u64::from(elf::SHF_STRINGS) != 0 { - SectionKind::OtherString - } else { - SectionKind::Other - } - } - elf::SHT_NOBITS => { - if flags & u64::from(elf::SHF_TLS) != 0 { - SectionKind::UninitializedTls - } else { - SectionKind::UninitializedData - } - } - elf::SHT_NOTE => SectionKind::Note, - elf::SHT_NULL - | elf::SHT_SYMTAB - | elf::SHT_STRTAB - | elf::SHT_RELA - | elf::SHT_HASH - | elf::SHT_DYNAMIC - | elf::SHT_REL - | elf::SHT_DYNSYM - | elf::SHT_GROUP => SectionKind::Metadata, - _ => SectionKind::Elf(sh_type), - } - } - - fn relocations(&self) -> ElfSectionRelocationIterator<'data, 'file, Elf, R> { - ElfSectionRelocationIterator { - section_index: self.index, - file: self.file, - relocations: None, - } - } - - fn flags(&self) -> SectionFlags { - SectionFlags::Elf { - sh_flags: self.section.sh_flags(self.file.endian).into(), - } - } -} - -/// A trait for generic access to [`elf::SectionHeader32`] and [`elf::SectionHeader64`]. -#[allow(missing_docs)] -pub trait SectionHeader: Debug + Pod { - type Elf: FileHeader; - type Word: Into; - type Endian: endian::Endian; - - fn sh_name(&self, endian: Self::Endian) -> u32; - fn sh_type(&self, endian: Self::Endian) -> u32; - fn sh_flags(&self, endian: Self::Endian) -> Self::Word; - fn sh_addr(&self, endian: Self::Endian) -> Self::Word; - fn sh_offset(&self, endian: Self::Endian) -> Self::Word; - fn sh_size(&self, endian: Self::Endian) -> Self::Word; - fn sh_link(&self, endian: Self::Endian) -> u32; - fn sh_info(&self, endian: Self::Endian) -> u32; - fn sh_addralign(&self, endian: Self::Endian) -> Self::Word; - fn sh_entsize(&self, endian: Self::Endian) -> Self::Word; - - /// Parse the section name from the string table. - fn name<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - strings: StringTable<'data, R>, - ) -> read::Result<&'data [u8]> { - strings - .get(self.sh_name(endian)) - .read_error("Invalid ELF section name offset") - } - - /// Return the offset and size of the section in the file. - /// - /// Returns `None` for sections that have no data in the file. - fn file_range(&self, endian: Self::Endian) -> Option<(u64, u64)> { - if self.sh_type(endian) == elf::SHT_NOBITS { - None - } else { - Some((self.sh_offset(endian).into(), self.sh_size(endian).into())) - } - } - - /// Return the section data. - /// - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values. - fn data<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result<&'data [u8]> { - if let Some((offset, size)) = self.file_range(endian) { - data.read_bytes_at(offset, size) - .read_error("Invalid ELF section size or offset") - } else { - Ok(&[]) - } - } - - /// Return the section data as a slice of the given type. - /// - /// Allows padding at the end of the data. - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values, including bad alignment. - fn data_as_array<'data, T: Pod, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result<&'data [T]> { - let mut data = self.data(endian, data).map(Bytes)?; - data.read_slice(data.len() / mem::size_of::()) - .read_error("Invalid ELF section size or offset") - } - - /// Return the strings in the section. - /// - /// Returns `Ok(None)` if the section does not contain strings. - /// Returns `Err` for invalid values. - fn strings<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.sh_type(endian) != elf::SHT_STRTAB { - return Ok(None); - } - let str_offset = self.sh_offset(endian).into(); - let str_size = self.sh_size(endian).into(); - let str_end = str_offset - .checked_add(str_size) - .read_error("Invalid ELF string section offset or size")?; - Ok(Some(StringTable::new(data, str_offset, str_end))) - } - - /// Return the symbols in the section. - /// - /// Also finds the linked string table in `sections`. - /// - /// `section_index` must be the 0-based index of this section, and is used - /// to find the corresponding extended section index table in `sections`. - /// - /// Returns `Ok(None)` if the section does not contain symbols. - /// Returns `Err` for invalid values. - fn symbols<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - sections: &SectionTable<'data, Self::Elf, R>, - section_index: SectionIndex, - ) -> read::Result>> { - let sh_type = self.sh_type(endian); - if sh_type != elf::SHT_SYMTAB && sh_type != elf::SHT_DYNSYM { - return Ok(None); - } - SymbolTable::parse(endian, data, sections, section_index, self).map(Some) - } - - /// Return the `Elf::Rel` entries in the section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if the section does not contain relocations. - /// Returns `Err` for invalid values. - fn rel<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result::Rel], SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_REL { - return Ok(None); - } - let rel = self - .data_as_array(endian, data) - .read_error("Invalid ELF relocation section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((rel, link))) - } - - /// Return the `Elf::Rela` entries in the section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if the section does not contain relocations. - /// Returns `Err` for invalid values. - fn rela<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result::Rela], SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_RELA { - return Ok(None); - } - let rela = self - .data_as_array(endian, data) - .read_error("Invalid ELF relocation section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((rela, link))) - } - - /// Return entries in a dynamic section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if the section type is not `SHT_DYNAMIC`. - /// Returns `Err` for invalid values. - fn dynamic<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result::Dyn], SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_DYNAMIC { - return Ok(None); - } - let dynamic = self - .data_as_array(endian, data) - .read_error("Invalid ELF dynamic section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((dynamic, link))) - } - - /// Return a note iterator for the section data. - /// - /// Returns `Ok(None)` if the section does not contain notes. - /// Returns `Err` for invalid values. - fn notes<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.sh_type(endian) != elf::SHT_NOTE { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF note section offset or size")?; - let notes = NoteIterator::new(endian, self.sh_addralign(endian), data)?; - Ok(Some(notes)) - } - - /// Return the contents of a group section. - /// - /// The first value is a `GRP_*` value, and the remaining values - /// are section indices. - /// - /// Returns `Ok(None)` if the section does not define a group. - /// Returns `Err` for invalid values. - fn group<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result])>> { - if self.sh_type(endian) != elf::SHT_GROUP { - return Ok(None); - } - let mut data = self - .data(endian, data) - .read_error("Invalid ELF group section offset or size") - .map(Bytes)?; - let flag = data - .read::>() - .read_error("Invalid ELF group section offset or size")? - .get(endian); - let count = data.len() / mem::size_of::>(); - let sections = data - .read_slice(count) - .read_error("Invalid ELF group section offset or size")?; - Ok(Some((flag, sections))) - } - - /// Return the header of a SysV hash section. - /// - /// Returns `Ok(None)` if the section does not contain a SysV hash. - /// Returns `Err` for invalid values. - fn hash_header<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.sh_type(endian) != elf::SHT_HASH { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF hash section offset or size")?; - let header = data - .read_at::>(0) - .read_error("Invalid hash header")?; - Ok(Some(header)) - } - - /// Return the contents of a SysV hash section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if the section does not contain a SysV hash. - /// Returns `Err` for invalid values. - fn hash<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_HASH { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF hash section offset or size")?; - let hash = HashTable::parse(endian, data)?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((hash, link))) - } - - /// Return the header of a GNU hash section. - /// - /// Returns `Ok(None)` if the section does not contain a GNU hash. - /// Returns `Err` for invalid values. - fn gnu_hash_header<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.sh_type(endian) != elf::SHT_GNU_HASH { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF GNU hash section offset or size")?; - let header = data - .read_at::>(0) - .read_error("Invalid GNU hash header")?; - Ok(Some(header)) - } - - /// Return the contents of a GNU hash section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if the section does not contain a GNU hash. - /// Returns `Err` for invalid values. - fn gnu_hash<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_GNU_HASH { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF GNU hash section offset or size")?; - let hash = GnuHashTable::parse(endian, data)?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((hash, link))) - } - - /// Return the contents of a `SHT_GNU_VERSYM` section. - /// - /// Also returns the linked symbol table index. - /// - /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERSYM`. - /// Returns `Err` for invalid values. - fn gnu_versym<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result], SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_GNU_VERSYM { - return Ok(None); - } - let versym = self - .data_as_array(endian, data) - .read_error("Invalid ELF GNU versym section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((versym, link))) - } - - /// Return an iterator for the entries of a `SHT_GNU_VERDEF` section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERDEF`. - /// Returns `Err` for invalid values. - fn gnu_verdef<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_GNU_VERDEF { - return Ok(None); - } - let verdef = self - .data(endian, data) - .read_error("Invalid ELF GNU verdef section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((VerdefIterator::new(endian, verdef), link))) - } - - /// Return an iterator for the entries of a `SHT_GNU_VERNEED` section. - /// - /// Also returns the linked string table index. - /// - /// Returns `Ok(None)` if the section type is not `SHT_GNU_VERNEED`. - /// Returns `Err` for invalid values. - fn gnu_verneed<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result, SectionIndex)>> { - if self.sh_type(endian) != elf::SHT_GNU_VERNEED { - return Ok(None); - } - let verneed = self - .data(endian, data) - .read_error("Invalid ELF GNU verneed section offset or size")?; - let link = SectionIndex(self.sh_link(endian) as usize); - Ok(Some((VerneedIterator::new(endian, verneed), link))) - } - - /// Return the contents of a `SHT_GNU_ATTRIBUTES` section. - /// - /// Returns `Ok(None)` if the section type is not `SHT_GNU_ATTRIBUTES`. - /// Returns `Err` for invalid values. - fn gnu_attributes<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.sh_type(endian) != elf::SHT_GNU_ATTRIBUTES { - return Ok(None); - } - self.attributes(endian, data).map(Some) - } - - /// Parse the contents of the section as attributes. - /// - /// This function does not check whether section type corresponds - /// to a section that contains attributes. - /// - /// Returns `Err` for invalid values. - fn attributes<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result> { - let data = self.data(endian, data)?; - AttributesSection::new(endian, data) - } - - /// Parse the compression header if present. - /// - /// Returns the header, and the offset and size of the compressed section data - /// in the file. - /// - /// Returns `Ok(None)` if the section flags do not have `SHF_COMPRESSED`. - /// Returns `Err` for invalid values. - fn compression<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result< - Option<( - &'data ::CompressionHeader, - u64, - u64, - )>, - > { - if (self.sh_flags(endian).into() & u64::from(elf::SHF_COMPRESSED)) == 0 { - return Ok(None); - } - let (section_offset, section_size) = self - .file_range(endian) - .read_error("Invalid ELF compressed section type")?; - let mut offset = section_offset; - let header = data - .read::<::CompressionHeader>(&mut offset) - .read_error("Invalid ELF compressed section offset")?; - let compressed_size = section_size - .checked_sub(offset - section_offset) - .read_error("Invalid ELF compressed section size")?; - Ok(Some((header, offset, compressed_size))) - } -} - -impl SectionHeader for elf::SectionHeader32 { - type Elf = elf::FileHeader32; - type Word = u32; - type Endian = Endian; - - #[inline] - fn sh_name(&self, endian: Self::Endian) -> u32 { - self.sh_name.get(endian) - } - - #[inline] - fn sh_type(&self, endian: Self::Endian) -> u32 { - self.sh_type.get(endian) - } - - #[inline] - fn sh_flags(&self, endian: Self::Endian) -> Self::Word { - self.sh_flags.get(endian) - } - - #[inline] - fn sh_addr(&self, endian: Self::Endian) -> Self::Word { - self.sh_addr.get(endian) - } - - #[inline] - fn sh_offset(&self, endian: Self::Endian) -> Self::Word { - self.sh_offset.get(endian) - } - - #[inline] - fn sh_size(&self, endian: Self::Endian) -> Self::Word { - self.sh_size.get(endian) - } - - #[inline] - fn sh_link(&self, endian: Self::Endian) -> u32 { - self.sh_link.get(endian) - } - - #[inline] - fn sh_info(&self, endian: Self::Endian) -> u32 { - self.sh_info.get(endian) - } - - #[inline] - fn sh_addralign(&self, endian: Self::Endian) -> Self::Word { - self.sh_addralign.get(endian) - } - - #[inline] - fn sh_entsize(&self, endian: Self::Endian) -> Self::Word { - self.sh_entsize.get(endian) - } -} - -impl SectionHeader for elf::SectionHeader64 { - type Word = u64; - type Endian = Endian; - type Elf = elf::FileHeader64; - - #[inline] - fn sh_name(&self, endian: Self::Endian) -> u32 { - self.sh_name.get(endian) - } - - #[inline] - fn sh_type(&self, endian: Self::Endian) -> u32 { - self.sh_type.get(endian) - } - - #[inline] - fn sh_flags(&self, endian: Self::Endian) -> Self::Word { - self.sh_flags.get(endian) - } - - #[inline] - fn sh_addr(&self, endian: Self::Endian) -> Self::Word { - self.sh_addr.get(endian) - } - - #[inline] - fn sh_offset(&self, endian: Self::Endian) -> Self::Word { - self.sh_offset.get(endian) - } - - #[inline] - fn sh_size(&self, endian: Self::Endian) -> Self::Word { - self.sh_size.get(endian) - } - - #[inline] - fn sh_link(&self, endian: Self::Endian) -> u32 { - self.sh_link.get(endian) - } - - #[inline] - fn sh_info(&self, endian: Self::Endian) -> u32 { - self.sh_info.get(endian) - } - - #[inline] - fn sh_addralign(&self, endian: Self::Endian) -> Self::Word { - self.sh_addralign.get(endian) - } - - #[inline] - fn sh_entsize(&self, endian: Self::Endian) -> Self::Word { - self.sh_entsize.get(endian) - } -} diff --git a/vendor/object/src/read/elf/segment.rs b/vendor/object/src/read/elf/segment.rs deleted file mode 100644 index 957117a..0000000 --- a/vendor/object/src/read/elf/segment.rs +++ /dev/null @@ -1,334 +0,0 @@ -use core::fmt::Debug; -use core::{mem, slice, str}; - -use crate::elf; -use crate::endian::{self, Endianness}; -use crate::pod::Pod; -use crate::read::{self, Bytes, ObjectSegment, ReadError, ReadRef, SegmentFlags}; - -use super::{ElfFile, FileHeader, NoteIterator}; - -/// An iterator for the segments in an [`ElfFile32`](super::ElfFile32). -pub type ElfSegmentIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSegmentIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the segments in an [`ElfFile64`](super::ElfFile64). -pub type ElfSegmentIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSegmentIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the segments in an [`ElfFile`]. -#[derive(Debug)] -pub struct ElfSegmentIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) iter: slice::Iter<'data, Elf::ProgramHeader>, -} - -impl<'data, 'file, Elf, R> Iterator for ElfSegmentIterator<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - type Item = ElfSegment<'data, 'file, Elf, R>; - - fn next(&mut self) -> Option { - for segment in self.iter.by_ref() { - if segment.p_type(self.file.endian) == elf::PT_LOAD { - return Some(ElfSegment { - file: self.file, - segment, - }); - } - } - None - } -} - -/// A segment in an [`ElfFile32`](super::ElfFile32). -pub type ElfSegment32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSegment<'data, 'file, elf::FileHeader32, R>; -/// A segment in an [`ElfFile64`](super::ElfFile64). -pub type ElfSegment64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSegment<'data, 'file, elf::FileHeader64, R>; - -/// A segment in an [`ElfFile`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -#[derive(Debug)] -pub struct ElfSegment<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file ElfFile<'data, Elf, R>, - pub(super) segment: &'data Elf::ProgramHeader, -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSegment<'data, 'file, Elf, R> { - fn bytes(&self) -> read::Result<&'data [u8]> { - self.segment - .data(self.file.endian, self.file.data) - .read_error("Invalid ELF segment size or offset") - } -} - -impl<'data, 'file, Elf, R> read::private::Sealed for ElfSegment<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Elf, R> ObjectSegment<'data> for ElfSegment<'data, 'file, Elf, R> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - #[inline] - fn address(&self) -> u64 { - self.segment.p_vaddr(self.file.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - self.segment.p_memsz(self.file.endian).into() - } - - #[inline] - fn align(&self) -> u64 { - self.segment.p_align(self.file.endian).into() - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - self.segment.file_range(self.file.endian) - } - - #[inline] - fn data(&self) -> read::Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> read::Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn name_bytes(&self) -> read::Result> { - Ok(None) - } - - #[inline] - fn name(&self) -> read::Result> { - Ok(None) - } - - #[inline] - fn flags(&self) -> SegmentFlags { - let p_flags = self.segment.p_flags(self.file.endian); - SegmentFlags::Elf { p_flags } - } -} - -/// A trait for generic access to [`elf::ProgramHeader32`] and [`elf::ProgramHeader64`]. -#[allow(missing_docs)] -pub trait ProgramHeader: Debug + Pod { - type Elf: FileHeader; - type Word: Into; - type Endian: endian::Endian; - - fn p_type(&self, endian: Self::Endian) -> u32; - fn p_flags(&self, endian: Self::Endian) -> u32; - fn p_offset(&self, endian: Self::Endian) -> Self::Word; - fn p_vaddr(&self, endian: Self::Endian) -> Self::Word; - fn p_paddr(&self, endian: Self::Endian) -> Self::Word; - fn p_filesz(&self, endian: Self::Endian) -> Self::Word; - fn p_memsz(&self, endian: Self::Endian) -> Self::Word; - fn p_align(&self, endian: Self::Endian) -> Self::Word; - - /// Return the offset and size of the segment in the file. - fn file_range(&self, endian: Self::Endian) -> (u64, u64) { - (self.p_offset(endian).into(), self.p_filesz(endian).into()) - } - - /// Return the segment data. - /// - /// Returns `Err` for invalid values. - fn data<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> Result<&'data [u8], ()> { - let (offset, size) = self.file_range(endian); - data.read_bytes_at(offset, size) - } - - /// Return the segment data as a slice of the given type. - /// - /// Allows padding at the end of the data. - /// Returns `Ok(&[])` if the segment has no data. - /// Returns `Err` for invalid values, including bad alignment. - fn data_as_array<'data, T: Pod, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> Result<&'data [T], ()> { - let mut data = self.data(endian, data).map(Bytes)?; - data.read_slice(data.len() / mem::size_of::()) - } - - /// Return the segment data in the given virtual address range - /// - /// Returns `Ok(None)` if the segment does not contain the address. - /// Returns `Err` for invalid values. - fn data_range<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - address: u64, - size: u64, - ) -> Result, ()> { - Ok(read::util::data_range( - self.data(endian, data)?, - self.p_vaddr(endian).into(), - address, - size, - )) - } - - /// Return entries in a dynamic segment. - /// - /// Returns `Ok(None)` if the segment is not `PT_DYNAMIC`. - /// Returns `Err` for invalid values. - fn dynamic<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result::Dyn]>> { - if self.p_type(endian) != elf::PT_DYNAMIC { - return Ok(None); - } - let dynamic = self - .data_as_array(endian, data) - .read_error("Invalid ELF dynamic segment offset or size")?; - Ok(Some(dynamic)) - } - - /// Return a note iterator for the segment data. - /// - /// Returns `Ok(None)` if the segment does not contain notes. - /// Returns `Err` for invalid values. - fn notes<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> read::Result>> { - if self.p_type(endian) != elf::PT_NOTE { - return Ok(None); - } - let data = self - .data(endian, data) - .read_error("Invalid ELF note segment offset or size")?; - let notes = NoteIterator::new(endian, self.p_align(endian), data)?; - Ok(Some(notes)) - } -} - -impl ProgramHeader for elf::ProgramHeader32 { - type Word = u32; - type Endian = Endian; - type Elf = elf::FileHeader32; - - #[inline] - fn p_type(&self, endian: Self::Endian) -> u32 { - self.p_type.get(endian) - } - - #[inline] - fn p_flags(&self, endian: Self::Endian) -> u32 { - self.p_flags.get(endian) - } - - #[inline] - fn p_offset(&self, endian: Self::Endian) -> Self::Word { - self.p_offset.get(endian) - } - - #[inline] - fn p_vaddr(&self, endian: Self::Endian) -> Self::Word { - self.p_vaddr.get(endian) - } - - #[inline] - fn p_paddr(&self, endian: Self::Endian) -> Self::Word { - self.p_paddr.get(endian) - } - - #[inline] - fn p_filesz(&self, endian: Self::Endian) -> Self::Word { - self.p_filesz.get(endian) - } - - #[inline] - fn p_memsz(&self, endian: Self::Endian) -> Self::Word { - self.p_memsz.get(endian) - } - - #[inline] - fn p_align(&self, endian: Self::Endian) -> Self::Word { - self.p_align.get(endian) - } -} - -impl ProgramHeader for elf::ProgramHeader64 { - type Word = u64; - type Endian = Endian; - type Elf = elf::FileHeader64; - - #[inline] - fn p_type(&self, endian: Self::Endian) -> u32 { - self.p_type.get(endian) - } - - #[inline] - fn p_flags(&self, endian: Self::Endian) -> u32 { - self.p_flags.get(endian) - } - - #[inline] - fn p_offset(&self, endian: Self::Endian) -> Self::Word { - self.p_offset.get(endian) - } - - #[inline] - fn p_vaddr(&self, endian: Self::Endian) -> Self::Word { - self.p_vaddr.get(endian) - } - - #[inline] - fn p_paddr(&self, endian: Self::Endian) -> Self::Word { - self.p_paddr.get(endian) - } - - #[inline] - fn p_filesz(&self, endian: Self::Endian) -> Self::Word { - self.p_filesz.get(endian) - } - - #[inline] - fn p_memsz(&self, endian: Self::Endian) -> Self::Word { - self.p_memsz.get(endian) - } - - #[inline] - fn p_align(&self, endian: Self::Endian) -> Self::Word { - self.p_align.get(endian) - } -} diff --git a/vendor/object/src/read/elf/symbol.rs b/vendor/object/src/read/elf/symbol.rs deleted file mode 100644 index 8ba707f..0000000 --- a/vendor/object/src/read/elf/symbol.rs +++ /dev/null @@ -1,595 +0,0 @@ -use alloc::fmt; -use alloc::vec::Vec; -use core::fmt::Debug; -use core::slice; -use core::str; - -use crate::endian::{self, Endianness}; -use crate::pod::Pod; -use crate::read::util::StringTable; -use crate::read::{ - self, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, SectionIndex, SymbolFlags, - SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection, -}; -use crate::{elf, U32}; - -use super::{FileHeader, SectionHeader, SectionTable}; - -/// A table of symbol entries in an ELF file. -/// -/// Also includes the string table used for the symbol names. -/// -/// Returned by [`SectionTable::symbols`]. -#[derive(Debug, Clone, Copy)] -pub struct SymbolTable<'data, Elf: FileHeader, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - section: SectionIndex, - string_section: SectionIndex, - shndx_section: SectionIndex, - symbols: &'data [Elf::Sym], - strings: StringTable<'data, R>, - shndx: &'data [U32], -} - -impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Elf, R> { - fn default() -> Self { - SymbolTable { - section: SectionIndex(0), - string_section: SectionIndex(0), - shndx_section: SectionIndex(0), - symbols: &[], - strings: Default::default(), - shndx: &[], - } - } -} - -impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> { - /// Parse the given symbol table section. - pub fn parse( - endian: Elf::Endian, - data: R, - sections: &SectionTable<'data, Elf, R>, - section_index: SectionIndex, - section: &Elf::SectionHeader, - ) -> read::Result> { - debug_assert!( - section.sh_type(endian) == elf::SHT_DYNSYM - || section.sh_type(endian) == elf::SHT_SYMTAB - ); - - let symbols = section - .data_as_array(endian, data) - .read_error("Invalid ELF symbol table data")?; - - let link = SectionIndex(section.sh_link(endian) as usize); - let strings = sections.strings(endian, data, link)?; - - let mut shndx_section = SectionIndex(0); - let mut shndx = &[][..]; - for (i, s) in sections.iter().enumerate() { - if s.sh_type(endian) == elf::SHT_SYMTAB_SHNDX - && s.sh_link(endian) as usize == section_index.0 - { - shndx_section = SectionIndex(i); - shndx = s - .data_as_array(endian, data) - .read_error("Invalid ELF symtab_shndx data")?; - } - } - - Ok(SymbolTable { - section: section_index, - string_section: link, - symbols, - strings, - shndx, - shndx_section, - }) - } - - /// Return the section index of this symbol table. - #[inline] - pub fn section(&self) -> SectionIndex { - self.section - } - - /// Return the section index of the shndx table. - #[inline] - pub fn shndx_section(&self) -> SectionIndex { - self.shndx_section - } - - /// Return the section index of the linked string table. - #[inline] - pub fn string_section(&self) -> SectionIndex { - self.string_section - } - - /// Return the string table used for the symbol names. - #[inline] - pub fn strings(&self) -> StringTable<'data, R> { - self.strings - } - - /// Return the symbol table. - #[inline] - pub fn symbols(&self) -> &'data [Elf::Sym] { - self.symbols - } - - /// Iterate over the symbols. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, Elf::Sym> { - self.symbols.iter() - } - - /// Return true if the symbol table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// The number of symbols. - #[inline] - pub fn len(&self) -> usize { - self.symbols.len() - } - - /// Return the symbol at the given index. - pub fn symbol(&self, index: usize) -> read::Result<&'data Elf::Sym> { - self.symbols - .get(index) - .read_error("Invalid ELF symbol index") - } - - /// Return the extended section index for the given symbol if present. - #[inline] - pub fn shndx(&self, endian: Elf::Endian, index: usize) -> Option { - self.shndx.get(index).map(|x| x.get(endian)) - } - - /// Return the section index for the given symbol. - /// - /// This uses the extended section index if present. - pub fn symbol_section( - &self, - endian: Elf::Endian, - symbol: &'data Elf::Sym, - index: usize, - ) -> read::Result> { - match symbol.st_shndx(endian) { - elf::SHN_UNDEF => Ok(None), - elf::SHN_XINDEX => self - .shndx(endian, index) - .read_error("Missing ELF symbol extended index") - .map(|index| Some(SectionIndex(index as usize))), - shndx if shndx < elf::SHN_LORESERVE => Ok(Some(SectionIndex(shndx.into()))), - _ => Ok(None), - } - } - - /// Return the symbol name for the given symbol. - pub fn symbol_name( - &self, - endian: Elf::Endian, - symbol: &'data Elf::Sym, - ) -> read::Result<&'data [u8]> { - symbol.name(endian, self.strings) - } - - /// Construct a map from addresses to a user-defined map entry. - pub fn map Option>( - &self, - endian: Elf::Endian, - f: F, - ) -> SymbolMap { - let mut symbols = Vec::with_capacity(self.symbols.len()); - for symbol in self.symbols { - if !symbol.is_definition(endian) { - continue; - } - if let Some(entry) = f(symbol) { - symbols.push(entry); - } - } - SymbolMap::new(symbols) - } -} - -/// A symbol table in an [`ElfFile32`](super::ElfFile32). -pub type ElfSymbolTable32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbolTable<'data, 'file, elf::FileHeader32, R>; -/// A symbol table in an [`ElfFile32`](super::ElfFile32). -pub type ElfSymbolTable64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbolTable<'data, 'file, elf::FileHeader64, R>; - -/// A symbol table in an [`ElfFile`](super::ElfFile). -#[derive(Debug, Clone, Copy)] -pub struct ElfSymbolTable<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) endian: Elf::Endian, - pub(super) symbols: &'file SymbolTable<'data, Elf, R>, -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed - for ElfSymbolTable<'data, 'file, Elf, R> -{ -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data> - for ElfSymbolTable<'data, 'file, Elf, R> -{ - type Symbol = ElfSymbol<'data, 'file, Elf, R>; - type SymbolIterator = ElfSymbolIterator<'data, 'file, Elf, R>; - - fn symbols(&self) -> Self::SymbolIterator { - ElfSymbolIterator { - endian: self.endian, - symbols: self.symbols, - index: 0, - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> read::Result { - let symbol = self.symbols.symbol(index.0)?; - Ok(ElfSymbol { - endian: self.endian, - symbols: self.symbols, - index, - symbol, - }) - } -} - -/// An iterator for the symbols in an [`ElfFile32`](super::ElfFile32). -pub type ElfSymbolIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbolIterator<'data, 'file, elf::FileHeader32, R>; -/// An iterator for the symbols in an [`ElfFile64`](super::ElfFile64). -pub type ElfSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbolIterator<'data, 'file, elf::FileHeader64, R>; - -/// An iterator for the symbols in an [`ElfFile`](super::ElfFile). -pub struct ElfSymbolIterator<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) endian: Elf::Endian, - pub(super) symbols: &'file SymbolTable<'data, Elf, R>, - pub(super) index: usize, -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> fmt::Debug - for ElfSymbolIterator<'data, 'file, Elf, R> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ElfSymbolIterator").finish() - } -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> Iterator - for ElfSymbolIterator<'data, 'file, Elf, R> -{ - type Item = ElfSymbol<'data, 'file, Elf, R>; - - fn next(&mut self) -> Option { - let index = self.index; - let symbol = self.symbols.symbols.get(index)?; - self.index += 1; - Some(ElfSymbol { - endian: self.endian, - symbols: self.symbols, - index: SymbolIndex(index), - symbol, - }) - } -} - -/// A symbol in an [`ElfFile32`](super::ElfFile32). -pub type ElfSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbol<'data, 'file, elf::FileHeader32, R>; -/// A symbol in an [`ElfFile64`](super::ElfFile64). -pub type ElfSymbol64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - ElfSymbol<'data, 'file, elf::FileHeader64, R>; - -/// A symbol in an [`ElfFile`](super::ElfFile). -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Debug, Clone, Copy)] -pub struct ElfSymbol<'data, 'file, Elf, R = &'data [u8]> -where - Elf: FileHeader, - R: ReadRef<'data>, -{ - pub(super) endian: Elf::Endian, - pub(super) symbols: &'file SymbolTable<'data, Elf, R>, - pub(super) index: SymbolIndex, - pub(super) symbol: &'data Elf::Sym, -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSymbol<'data, 'file, Elf, R> { - /// Return a reference to the raw symbol structure. - #[inline] - pub fn raw_symbol(&self) -> &'data Elf::Sym { - self.symbol - } -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed - for ElfSymbol<'data, 'file, Elf, R> -{ -} - -impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data> - for ElfSymbol<'data, 'file, Elf, R> -{ - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - fn name_bytes(&self) -> read::Result<&'data [u8]> { - self.symbol.name(self.endian, self.symbols.strings()) - } - - fn name(&self) -> read::Result<&'data str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 ELF symbol name") - } - - #[inline] - fn address(&self) -> u64 { - self.symbol.st_value(self.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - self.symbol.st_size(self.endian).into() - } - - fn kind(&self) -> SymbolKind { - match self.symbol.st_type() { - elf::STT_NOTYPE if self.index.0 == 0 => SymbolKind::Null, - elf::STT_NOTYPE => SymbolKind::Unknown, - elf::STT_OBJECT | elf::STT_COMMON => SymbolKind::Data, - elf::STT_FUNC | elf::STT_GNU_IFUNC => SymbolKind::Text, - elf::STT_SECTION => SymbolKind::Section, - elf::STT_FILE => SymbolKind::File, - elf::STT_TLS => SymbolKind::Tls, - _ => SymbolKind::Unknown, - } - } - - fn section(&self) -> SymbolSection { - match self.symbol.st_shndx(self.endian) { - elf::SHN_UNDEF => SymbolSection::Undefined, - elf::SHN_ABS => { - if self.symbol.st_type() == elf::STT_FILE { - SymbolSection::None - } else { - SymbolSection::Absolute - } - } - elf::SHN_COMMON => SymbolSection::Common, - elf::SHN_XINDEX => match self.symbols.shndx(self.endian, self.index.0) { - Some(index) => SymbolSection::Section(SectionIndex(index as usize)), - None => SymbolSection::Unknown, - }, - index if index < elf::SHN_LORESERVE => { - SymbolSection::Section(SectionIndex(index as usize)) - } - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.st_shndx(self.endian) == elf::SHN_UNDEF - } - - #[inline] - fn is_definition(&self) -> bool { - self.symbol.is_definition(self.endian) - } - - #[inline] - fn is_common(&self) -> bool { - self.symbol.st_shndx(self.endian) == elf::SHN_COMMON - } - - #[inline] - fn is_weak(&self) -> bool { - self.symbol.st_bind() == elf::STB_WEAK - } - - fn scope(&self) -> SymbolScope { - if self.symbol.st_shndx(self.endian) == elf::SHN_UNDEF { - SymbolScope::Unknown - } else { - match self.symbol.st_bind() { - elf::STB_LOCAL => SymbolScope::Compilation, - elf::STB_GLOBAL | elf::STB_WEAK => { - if self.symbol.st_visibility() == elf::STV_HIDDEN { - SymbolScope::Linkage - } else { - SymbolScope::Dynamic - } - } - _ => SymbolScope::Unknown, - } - } - } - - #[inline] - fn is_global(&self) -> bool { - self.symbol.st_bind() != elf::STB_LOCAL - } - - #[inline] - fn is_local(&self) -> bool { - self.symbol.st_bind() == elf::STB_LOCAL - } - - #[inline] - fn flags(&self) -> SymbolFlags { - SymbolFlags::Elf { - st_info: self.symbol.st_info(), - st_other: self.symbol.st_other(), - } - } -} - -/// A trait for generic access to [`elf::Sym32`] and [`elf::Sym64`]. -#[allow(missing_docs)] -pub trait Sym: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - - fn st_name(&self, endian: Self::Endian) -> u32; - fn st_info(&self) -> u8; - fn st_bind(&self) -> u8; - fn st_type(&self) -> u8; - fn st_other(&self) -> u8; - fn st_visibility(&self) -> u8; - fn st_shndx(&self, endian: Self::Endian) -> u16; - fn st_value(&self, endian: Self::Endian) -> Self::Word; - fn st_size(&self, endian: Self::Endian) -> Self::Word; - - /// Parse the symbol name from the string table. - fn name<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - strings: StringTable<'data, R>, - ) -> read::Result<&'data [u8]> { - strings - .get(self.st_name(endian)) - .read_error("Invalid ELF symbol name offset") - } - - /// Return true if the symbol is undefined. - #[inline] - fn is_undefined(&self, endian: Self::Endian) -> bool { - self.st_shndx(endian) == elf::SHN_UNDEF - } - - /// Return true if the symbol is a definition of a function or data object. - fn is_definition(&self, endian: Self::Endian) -> bool { - let shndx = self.st_shndx(endian); - if shndx == elf::SHN_UNDEF || (shndx >= elf::SHN_LORESERVE && shndx != elf::SHN_XINDEX) { - return false; - } - match self.st_type() { - elf::STT_NOTYPE => self.st_size(endian).into() != 0, - elf::STT_FUNC | elf::STT_OBJECT => true, - _ => false, - } - } -} - -impl Sym for elf::Sym32 { - type Word = u32; - type Endian = Endian; - - #[inline] - fn st_name(&self, endian: Self::Endian) -> u32 { - self.st_name.get(endian) - } - - #[inline] - fn st_info(&self) -> u8 { - self.st_info - } - - #[inline] - fn st_bind(&self) -> u8 { - self.st_bind() - } - - #[inline] - fn st_type(&self) -> u8 { - self.st_type() - } - - #[inline] - fn st_other(&self) -> u8 { - self.st_other - } - - #[inline] - fn st_visibility(&self) -> u8 { - self.st_visibility() - } - - #[inline] - fn st_shndx(&self, endian: Self::Endian) -> u16 { - self.st_shndx.get(endian) - } - - #[inline] - fn st_value(&self, endian: Self::Endian) -> Self::Word { - self.st_value.get(endian) - } - - #[inline] - fn st_size(&self, endian: Self::Endian) -> Self::Word { - self.st_size.get(endian) - } -} - -impl Sym for elf::Sym64 { - type Word = u64; - type Endian = Endian; - - #[inline] - fn st_name(&self, endian: Self::Endian) -> u32 { - self.st_name.get(endian) - } - - #[inline] - fn st_info(&self) -> u8 { - self.st_info - } - - #[inline] - fn st_bind(&self) -> u8 { - self.st_bind() - } - - #[inline] - fn st_type(&self) -> u8 { - self.st_type() - } - - #[inline] - fn st_other(&self) -> u8 { - self.st_other - } - - #[inline] - fn st_visibility(&self) -> u8 { - self.st_visibility() - } - - #[inline] - fn st_shndx(&self, endian: Self::Endian) -> u16 { - self.st_shndx.get(endian) - } - - #[inline] - fn st_value(&self, endian: Self::Endian) -> Self::Word { - self.st_value.get(endian) - } - - #[inline] - fn st_size(&self, endian: Self::Endian) -> Self::Word { - self.st_size.get(endian) - } -} diff --git a/vendor/object/src/read/elf/version.rs b/vendor/object/src/read/elf/version.rs deleted file mode 100644 index 28eeed0..0000000 --- a/vendor/object/src/read/elf/version.rs +++ /dev/null @@ -1,424 +0,0 @@ -use alloc::vec::Vec; - -use crate::read::{Bytes, ReadError, ReadRef, Result, StringTable}; -use crate::{elf, endian}; - -use super::FileHeader; - -/// A version index. -#[derive(Debug, Default, Clone, Copy)] -pub struct VersionIndex(pub u16); - -impl VersionIndex { - /// Return the version index. - pub fn index(&self) -> u16 { - self.0 & elf::VERSYM_VERSION - } - - /// Return true if it is the local index. - pub fn is_local(&self) -> bool { - self.index() == elf::VER_NDX_LOCAL - } - - /// Return true if it is the global index. - pub fn is_global(&self) -> bool { - self.index() == elf::VER_NDX_GLOBAL - } - - /// Return the hidden flag. - pub fn is_hidden(&self) -> bool { - self.0 & elf::VERSYM_HIDDEN != 0 - } -} - -/// A version definition or requirement. -/// -/// This is derived from entries in the [`elf::SHT_GNU_VERDEF`] and [`elf::SHT_GNU_VERNEED`] sections. -#[derive(Debug, Default, Clone, Copy)] -pub struct Version<'data> { - name: &'data [u8], - hash: u32, - // Used to keep track of valid indices in `VersionTable`. - valid: bool, -} - -impl<'data> Version<'data> { - /// Return the version name. - pub fn name(&self) -> &'data [u8] { - self.name - } - - /// Return hash of the version name. - pub fn hash(&self) -> u32 { - self.hash - } -} - -/// A table of version definitions and requirements. -/// -/// It allows looking up the version information for a given symbol index. -/// -/// This is derived from entries in the [`elf::SHT_GNU_VERSYM`], [`elf::SHT_GNU_VERDEF`] -/// and [`elf::SHT_GNU_VERNEED`] sections. -/// -/// Returned by [`SectionTable::versions`](super::SectionTable::versions). -#[derive(Debug, Clone)] -pub struct VersionTable<'data, Elf: FileHeader> { - symbols: &'data [elf::Versym], - versions: Vec>, -} - -impl<'data, Elf: FileHeader> Default for VersionTable<'data, Elf> { - fn default() -> Self { - VersionTable { - symbols: &[], - versions: Vec::new(), - } - } -} - -impl<'data, Elf: FileHeader> VersionTable<'data, Elf> { - /// Parse the version sections. - pub fn parse>( - endian: Elf::Endian, - versyms: &'data [elf::Versym], - verdefs: Option>, - verneeds: Option>, - strings: StringTable<'data, R>, - ) -> Result { - let mut max_index = 0; - if let Some(mut verdefs) = verdefs.clone() { - while let Some((verdef, _)) = verdefs.next()? { - if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 { - continue; - } - let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION; - if max_index < index { - max_index = index; - } - } - } - if let Some(mut verneeds) = verneeds.clone() { - while let Some((_, mut vernauxs)) = verneeds.next()? { - while let Some(vernaux) = vernauxs.next()? { - let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION; - if max_index < index { - max_index = index; - } - } - } - } - - // Indices should be sequential, but this could be up to - // 32k * size_of::() if max_index is bad. - let mut versions = vec![Version::default(); max_index as usize + 1]; - - if let Some(mut verdefs) = verdefs { - while let Some((verdef, mut verdauxs)) = verdefs.next()? { - if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 { - continue; - } - let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION; - if index <= elf::VER_NDX_GLOBAL { - // TODO: return error? - continue; - } - if let Some(verdaux) = verdauxs.next()? { - versions[usize::from(index)] = Version { - name: verdaux.name(endian, strings)?, - hash: verdef.vd_hash.get(endian), - valid: true, - }; - } - } - } - if let Some(mut verneeds) = verneeds { - while let Some((_, mut vernauxs)) = verneeds.next()? { - while let Some(vernaux) = vernauxs.next()? { - let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION; - if index <= elf::VER_NDX_GLOBAL { - // TODO: return error? - continue; - } - versions[usize::from(index)] = Version { - name: vernaux.name(endian, strings)?, - hash: vernaux.vna_hash.get(endian), - valid: true, - }; - } - } - } - - Ok(VersionTable { - symbols: versyms, - versions, - }) - } - - /// Return true if the version table is empty. - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// Return version index for a given symbol index. - pub fn version_index(&self, endian: Elf::Endian, index: usize) -> VersionIndex { - let version_index = match self.symbols.get(index) { - Some(x) => x.0.get(endian), - // Ideally this would be VER_NDX_LOCAL for undefined symbols, - // but currently there are no checks that need this distinction. - None => elf::VER_NDX_GLOBAL, - }; - VersionIndex(version_index) - } - - /// Return version information for a given symbol version index. - /// - /// Returns `Ok(None)` for local and global versions. - /// Returns `Err(_)` if index is invalid. - pub fn version(&self, index: VersionIndex) -> Result>> { - if index.index() <= elf::VER_NDX_GLOBAL { - return Ok(None); - } - self.versions - .get(usize::from(index.index())) - .filter(|version| version.valid) - .read_error("Invalid ELF symbol version index") - .map(Some) - } - - /// Return true if the given symbol index satisfies the requirements of `need`. - /// - /// Returns false for any error. - /// - /// Note: this function hasn't been fully tested and is likely to be incomplete. - pub fn matches(&self, endian: Elf::Endian, index: usize, need: Option<&Version<'_>>) -> bool { - let version_index = self.version_index(endian, index); - let def = match self.version(version_index) { - Ok(def) => def, - Err(_) => return false, - }; - match (def, need) { - (Some(def), Some(need)) => need.hash == def.hash && need.name == def.name, - (None, Some(_need)) => { - // Version must be present if needed. - false - } - (Some(_def), None) => { - // For a dlsym call, use the newest version. - // TODO: if not a dlsym call, then use the oldest version. - !version_index.is_hidden() - } - (None, None) => true, - } - } -} - -/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERDEF`] section. -#[derive(Debug, Clone)] -pub struct VerdefIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> VerdefIterator<'data, Elf> { - pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self { - VerdefIterator { - endian, - data: Bytes(data), - } - } - - /// Return the next `Verdef` entry. - pub fn next( - &mut self, - ) -> Result, VerdauxIterator<'data, Elf>)>> { - if self.data.is_empty() { - return Ok(None); - } - - let verdef = self - .data - .read_at::>(0) - .read_error("ELF verdef is too short")?; - - let mut verdaux_data = self.data; - verdaux_data - .skip(verdef.vd_aux.get(self.endian) as usize) - .read_error("Invalid ELF vd_aux")?; - let verdaux = - VerdauxIterator::new(self.endian, verdaux_data.0, verdef.vd_cnt.get(self.endian)); - - let next = verdef.vd_next.get(self.endian); - if next != 0 { - self.data - .skip(next as usize) - .read_error("Invalid ELF vd_next")?; - } else { - self.data = Bytes(&[]); - } - Ok(Some((verdef, verdaux))) - } -} - -/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERDEF`] section. -#[derive(Debug, Clone)] -pub struct VerdauxIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, - count: u16, -} - -impl<'data, Elf: FileHeader> VerdauxIterator<'data, Elf> { - pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self { - VerdauxIterator { - endian, - data: Bytes(data), - count, - } - } - - /// Return the next `Verdaux` entry. - pub fn next(&mut self) -> Result>> { - if self.count == 0 { - return Ok(None); - } - - let verdaux = self - .data - .read_at::>(0) - .read_error("ELF verdaux is too short")?; - - self.data - .skip(verdaux.vda_next.get(self.endian) as usize) - .read_error("Invalid ELF vda_next")?; - self.count -= 1; - Ok(Some(verdaux)) - } -} - -/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERNEED`] section. -#[derive(Debug, Clone)] -pub struct VerneedIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, -} - -impl<'data, Elf: FileHeader> VerneedIterator<'data, Elf> { - pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self { - VerneedIterator { - endian, - data: Bytes(data), - } - } - - /// Return the next `Verneed` entry. - pub fn next( - &mut self, - ) -> Result< - Option<( - &'data elf::Verneed, - VernauxIterator<'data, Elf>, - )>, - > { - if self.data.is_empty() { - return Ok(None); - } - - let verneed = self - .data - .read_at::>(0) - .read_error("ELF verneed is too short")?; - - let mut vernaux_data = self.data; - vernaux_data - .skip(verneed.vn_aux.get(self.endian) as usize) - .read_error("Invalid ELF vn_aux")?; - let vernaux = - VernauxIterator::new(self.endian, vernaux_data.0, verneed.vn_cnt.get(self.endian)); - - let next = verneed.vn_next.get(self.endian); - if next != 0 { - self.data - .skip(next as usize) - .read_error("Invalid ELF vn_next")?; - } else { - self.data = Bytes(&[]); - } - Ok(Some((verneed, vernaux))) - } -} - -/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERNEED`] section. -#[derive(Debug, Clone)] -pub struct VernauxIterator<'data, Elf: FileHeader> { - endian: Elf::Endian, - data: Bytes<'data>, - count: u16, -} - -impl<'data, Elf: FileHeader> VernauxIterator<'data, Elf> { - pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self { - VernauxIterator { - endian, - data: Bytes(data), - count, - } - } - - /// Return the next `Vernaux` entry. - pub fn next(&mut self) -> Result>> { - if self.count == 0 { - return Ok(None); - } - - let vernaux = self - .data - .read_at::>(0) - .read_error("ELF vernaux is too short")?; - - self.data - .skip(vernaux.vna_next.get(self.endian) as usize) - .read_error("Invalid ELF vna_next")?; - self.count -= 1; - Ok(Some(vernaux)) - } -} - -impl elf::Verdaux { - /// Parse the version name from the string table. - pub fn name<'data, R: ReadRef<'data>>( - &self, - endian: Endian, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - strings - .get(self.vda_name.get(endian)) - .read_error("Invalid ELF vda_name") - } -} - -impl elf::Verneed { - /// Parse the file from the string table. - pub fn file<'data, R: ReadRef<'data>>( - &self, - endian: Endian, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - strings - .get(self.vn_file.get(endian)) - .read_error("Invalid ELF vn_file") - } -} - -impl elf::Vernaux { - /// Parse the version name from the string table. - pub fn name<'data, R: ReadRef<'data>>( - &self, - endian: Endian, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - strings - .get(self.vna_name.get(endian)) - .read_error("Invalid ELF vna_name") - } -} diff --git a/vendor/object/src/read/macho/dyld_cache.rs b/vendor/object/src/read/macho/dyld_cache.rs deleted file mode 100644 index 0f5dfc5..0000000 --- a/vendor/object/src/read/macho/dyld_cache.rs +++ /dev/null @@ -1,344 +0,0 @@ -use alloc::vec::Vec; -use core::slice; - -use crate::read::{Error, File, ReadError, ReadRef, Result}; -use crate::{macho, Architecture, Endian, Endianness}; - -/// A parsed representation of the dyld shared cache. -#[derive(Debug)] -pub struct DyldCache<'data, E = Endianness, R = &'data [u8]> -where - E: Endian, - R: ReadRef<'data>, -{ - endian: E, - data: R, - subcaches: Vec>, - mappings: &'data [macho::DyldCacheMappingInfo], - images: &'data [macho::DyldCacheImageInfo], - arch: Architecture, -} - -/// Information about a subcache. -#[derive(Debug)] -pub struct DyldSubCache<'data, E = Endianness, R = &'data [u8]> -where - E: Endian, - R: ReadRef<'data>, -{ - data: R, - mappings: &'data [macho::DyldCacheMappingInfo], -} - -// This is the offset of the images_across_all_subcaches_count field. -const MIN_HEADER_SIZE_SUBCACHES: u32 = 0x1c4; - -impl<'data, E, R> DyldCache<'data, E, R> -where - E: Endian, - R: ReadRef<'data>, -{ - /// Parse the raw dyld shared cache data. - /// - /// For shared caches from macOS 12 / iOS 15 and above, the subcache files need to be - /// supplied as well, in the correct order, with the `.symbols` subcache last (if present). - /// For example, `data` would be the data for `dyld_shared_cache_x86_64`, - /// and `subcache_data` would be the data for `[dyld_shared_cache_x86_64.1, dyld_shared_cache_x86_64.2, ...]`. - pub fn parse(data: R, subcache_data: &[R]) -> Result { - let header = macho::DyldCacheHeader::parse(data)?; - let (arch, endian) = header.parse_magic()?; - let mappings = header.mappings(endian, data)?; - - let symbols_subcache_uuid = header.symbols_subcache_uuid(endian); - let subcaches_info = header.subcaches(endian, data)?.unwrap_or(&[]); - - if subcache_data.len() != subcaches_info.len() + symbols_subcache_uuid.is_some() as usize { - return Err(Error("Incorrect number of SubCaches")); - } - - // Split out the .symbols subcache data from the other subcaches. - let (symbols_subcache_data_and_uuid, subcache_data) = - if let Some(symbols_uuid) = symbols_subcache_uuid { - let (sym_data, rest_data) = subcache_data.split_last().unwrap(); - (Some((*sym_data, symbols_uuid)), rest_data) - } else { - (None, subcache_data) - }; - - // Read the regular SubCaches (.1, .2, ...), if present. - let mut subcaches = Vec::new(); - for (&data, info) in subcache_data.iter().zip(subcaches_info.iter()) { - let sc_header = macho::DyldCacheHeader::::parse(data)?; - if sc_header.uuid != info.uuid { - return Err(Error("Unexpected SubCache UUID")); - } - let mappings = sc_header.mappings(endian, data)?; - subcaches.push(DyldSubCache { data, mappings }); - } - - // Read the .symbols SubCache, if present. - // Other than the UUID verification, the symbols SubCache is currently unused. - let _symbols_subcache = match symbols_subcache_data_and_uuid { - Some((data, uuid)) => { - let sc_header = macho::DyldCacheHeader::::parse(data)?; - if sc_header.uuid != uuid { - return Err(Error("Unexpected .symbols SubCache UUID")); - } - let mappings = sc_header.mappings(endian, data)?; - Some(DyldSubCache { data, mappings }) - } - None => None, - }; - - let images = header.images(endian, data)?; - Ok(DyldCache { - endian, - data, - subcaches, - mappings, - images, - arch, - }) - } - - /// Get the architecture type of the file. - pub fn architecture(&self) -> Architecture { - self.arch - } - - /// Get the endianness of the file. - #[inline] - pub fn endianness(&self) -> Endianness { - if self.is_little_endian() { - Endianness::Little - } else { - Endianness::Big - } - } - - /// Return true if the file is little endian, false if it is big endian. - pub fn is_little_endian(&self) -> bool { - self.endian.is_little_endian() - } - - /// Iterate over the images in this cache. - pub fn images<'cache>(&'cache self) -> DyldCacheImageIterator<'data, 'cache, E, R> { - DyldCacheImageIterator { - cache: self, - iter: self.images.iter(), - } - } - - /// Find the address in a mapping and return the cache or subcache data it was found in, - /// together with the translated file offset. - pub fn data_and_offset_for_address(&self, address: u64) -> Option<(R, u64)> { - if let Some(file_offset) = address_to_file_offset(address, self.endian, self.mappings) { - return Some((self.data, file_offset)); - } - for subcache in &self.subcaches { - if let Some(file_offset) = - address_to_file_offset(address, self.endian, subcache.mappings) - { - return Some((subcache.data, file_offset)); - } - } - None - } -} - -/// An iterator over all the images (dylibs) in the dyld shared cache. -#[derive(Debug)] -pub struct DyldCacheImageIterator<'data, 'cache, E = Endianness, R = &'data [u8]> -where - E: Endian, - R: ReadRef<'data>, -{ - cache: &'cache DyldCache<'data, E, R>, - iter: slice::Iter<'data, macho::DyldCacheImageInfo>, -} - -impl<'data, 'cache, E, R> Iterator for DyldCacheImageIterator<'data, 'cache, E, R> -where - E: Endian, - R: ReadRef<'data>, -{ - type Item = DyldCacheImage<'data, 'cache, E, R>; - - fn next(&mut self) -> Option> { - let image_info = self.iter.next()?; - Some(DyldCacheImage { - cache: self.cache, - image_info, - }) - } -} - -/// One image (dylib) from inside the dyld shared cache. -#[derive(Debug)] -pub struct DyldCacheImage<'data, 'cache, E = Endianness, R = &'data [u8]> -where - E: Endian, - R: ReadRef<'data>, -{ - pub(crate) cache: &'cache DyldCache<'data, E, R>, - image_info: &'data macho::DyldCacheImageInfo, -} - -impl<'data, 'cache, E, R> DyldCacheImage<'data, 'cache, E, R> -where - E: Endian, - R: ReadRef<'data>, -{ - /// The file system path of this image. - pub fn path(&self) -> Result<&'data str> { - let path = self.image_info.path(self.cache.endian, self.cache.data)?; - // The path should always be ascii, so from_utf8 should always succeed. - let path = core::str::from_utf8(path).map_err(|_| Error("Path string not valid utf-8"))?; - Ok(path) - } - - /// The subcache data which contains the Mach-O header for this image, - /// together with the file offset at which this image starts. - pub fn image_data_and_offset(&self) -> Result<(R, u64)> { - let address = self.image_info.address.get(self.cache.endian); - self.cache - .data_and_offset_for_address(address) - .ok_or(Error("Address not found in any mapping")) - } - - /// Parse this image into an Object. - pub fn parse_object(&self) -> Result> { - File::parse_dyld_cache_image(self) - } -} - -impl macho::DyldCacheHeader { - /// Read the dyld cache header. - pub fn parse<'data, R: ReadRef<'data>>(data: R) -> Result<&'data Self> { - data.read_at::>(0) - .read_error("Invalid dyld cache header size or alignment") - } - - /// Returns (arch, endian) based on the magic string. - pub fn parse_magic(&self) -> Result<(Architecture, E)> { - let (arch, is_big_endian) = match &self.magic { - b"dyld_v1 i386\0" => (Architecture::I386, false), - b"dyld_v1 x86_64\0" => (Architecture::X86_64, false), - b"dyld_v1 x86_64h\0" => (Architecture::X86_64, false), - b"dyld_v1 ppc\0" => (Architecture::PowerPc, true), - b"dyld_v1 armv6\0" => (Architecture::Arm, false), - b"dyld_v1 armv7\0" => (Architecture::Arm, false), - b"dyld_v1 armv7f\0" => (Architecture::Arm, false), - b"dyld_v1 armv7s\0" => (Architecture::Arm, false), - b"dyld_v1 armv7k\0" => (Architecture::Arm, false), - b"dyld_v1 arm64\0" => (Architecture::Aarch64, false), - b"dyld_v1 arm64e\0" => (Architecture::Aarch64, false), - _ => return Err(Error("Unrecognized dyld cache magic")), - }; - let endian = - E::from_big_endian(is_big_endian).read_error("Unsupported dyld cache endian")?; - Ok((arch, endian)) - } - - /// Return the mapping information table. - pub fn mappings<'data, R: ReadRef<'data>>( - &self, - endian: E, - data: R, - ) -> Result<&'data [macho::DyldCacheMappingInfo]> { - data.read_slice_at::>( - self.mapping_offset.get(endian).into(), - self.mapping_count.get(endian) as usize, - ) - .read_error("Invalid dyld cache mapping size or alignment") - } - - /// Return the information about subcaches, if present. - pub fn subcaches<'data, R: ReadRef<'data>>( - &self, - endian: E, - data: R, - ) -> Result]>> { - if self.mapping_offset.get(endian) >= MIN_HEADER_SIZE_SUBCACHES { - let subcaches = data - .read_slice_at::>( - self.subcaches_offset.get(endian).into(), - self.subcaches_count.get(endian) as usize, - ) - .read_error("Invalid dyld subcaches size or alignment")?; - Ok(Some(subcaches)) - } else { - Ok(None) - } - } - - /// Return the UUID for the .symbols subcache, if present. - pub fn symbols_subcache_uuid(&self, endian: E) -> Option<[u8; 16]> { - if self.mapping_offset.get(endian) >= MIN_HEADER_SIZE_SUBCACHES { - let uuid = self.symbols_subcache_uuid; - if uuid != [0; 16] { - return Some(uuid); - } - } - None - } - - /// Return the image information table. - pub fn images<'data, R: ReadRef<'data>>( - &self, - endian: E, - data: R, - ) -> Result<&'data [macho::DyldCacheImageInfo]> { - if self.mapping_offset.get(endian) >= MIN_HEADER_SIZE_SUBCACHES { - data.read_slice_at::>( - self.images_across_all_subcaches_offset.get(endian).into(), - self.images_across_all_subcaches_count.get(endian) as usize, - ) - .read_error("Invalid dyld cache image size or alignment") - } else { - data.read_slice_at::>( - self.images_offset.get(endian).into(), - self.images_count.get(endian) as usize, - ) - .read_error("Invalid dyld cache image size or alignment") - } - } -} - -impl macho::DyldCacheImageInfo { - /// The file system path of this image. - pub fn path<'data, R: ReadRef<'data>>(&self, endian: E, data: R) -> Result<&'data [u8]> { - let r_start = self.path_file_offset.get(endian).into(); - let r_end = data.len().read_error("Couldn't get data len()")?; - data.read_bytes_at_until(r_start..r_end, 0) - .read_error("Couldn't read dyld cache image path") - } - - /// Find the file offset of the image by looking up its address in the mappings. - pub fn file_offset( - &self, - endian: E, - mappings: &[macho::DyldCacheMappingInfo], - ) -> Result { - let address = self.address.get(endian); - address_to_file_offset(address, endian, mappings) - .read_error("Invalid dyld cache image address") - } -} - -/// Find the file offset of the image by looking up its address in the mappings. -pub fn address_to_file_offset( - address: u64, - endian: E, - mappings: &[macho::DyldCacheMappingInfo], -) -> Option { - for mapping in mappings { - let mapping_address = mapping.address.get(endian); - if address >= mapping_address - && address < mapping_address.wrapping_add(mapping.size.get(endian)) - { - return Some(address - mapping_address + mapping.file_offset.get(endian)); - } - } - None -} diff --git a/vendor/object/src/read/macho/fat.rs b/vendor/object/src/read/macho/fat.rs deleted file mode 100644 index a481351..0000000 --- a/vendor/object/src/read/macho/fat.rs +++ /dev/null @@ -1,122 +0,0 @@ -use crate::read::{Architecture, Error, ReadError, ReadRef, Result}; -use crate::{macho, BigEndian, Pod}; - -pub use macho::{FatArch32, FatArch64, FatHeader}; - -impl FatHeader { - /// Attempt to parse a fat header. - /// - /// Does not validate the magic value. - pub fn parse<'data, R: ReadRef<'data>>(file: R) -> Result<&'data FatHeader> { - file.read_at::(0) - .read_error("Invalid fat header size or alignment") - } - - /// Attempt to parse a fat header and 32-bit fat arches. - pub fn parse_arch32<'data, R: ReadRef<'data>>(file: R) -> Result<&'data [FatArch32]> { - let mut offset = 0; - let header = file - .read::(&mut offset) - .read_error("Invalid fat header size or alignment")?; - if header.magic.get(BigEndian) != macho::FAT_MAGIC { - return Err(Error("Invalid 32-bit fat magic")); - } - file.read_slice::(&mut offset, header.nfat_arch.get(BigEndian) as usize) - .read_error("Invalid nfat_arch") - } - - /// Attempt to parse a fat header and 64-bit fat arches. - pub fn parse_arch64<'data, R: ReadRef<'data>>(file: R) -> Result<&'data [FatArch64]> { - let mut offset = 0; - let header = file - .read::(&mut offset) - .read_error("Invalid fat header size or alignment")?; - if header.magic.get(BigEndian) != macho::FAT_MAGIC_64 { - return Err(Error("Invalid 64-bit fat magic")); - } - file.read_slice::(&mut offset, header.nfat_arch.get(BigEndian) as usize) - .read_error("Invalid nfat_arch") - } -} - -/// A trait for generic access to [`macho::FatArch32`] and [`macho::FatArch64`]. -#[allow(missing_docs)] -pub trait FatArch: Pod { - type Word: Into; - - fn cputype(&self) -> u32; - fn cpusubtype(&self) -> u32; - fn offset(&self) -> Self::Word; - fn size(&self) -> Self::Word; - fn align(&self) -> u32; - - fn architecture(&self) -> Architecture { - match self.cputype() { - macho::CPU_TYPE_ARM => Architecture::Arm, - macho::CPU_TYPE_ARM64 => Architecture::Aarch64, - macho::CPU_TYPE_X86 => Architecture::I386, - macho::CPU_TYPE_X86_64 => Architecture::X86_64, - macho::CPU_TYPE_MIPS => Architecture::Mips, - macho::CPU_TYPE_POWERPC => Architecture::PowerPc, - macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64, - _ => Architecture::Unknown, - } - } - - fn file_range(&self) -> (u64, u64) { - (self.offset().into(), self.size().into()) - } - - fn data<'data, R: ReadRef<'data>>(&self, file: R) -> Result<&'data [u8]> { - file.read_bytes_at(self.offset().into(), self.size().into()) - .read_error("Invalid fat arch offset or size") - } -} - -impl FatArch for FatArch32 { - type Word = u32; - - fn cputype(&self) -> u32 { - self.cputype.get(BigEndian) - } - - fn cpusubtype(&self) -> u32 { - self.cpusubtype.get(BigEndian) - } - - fn offset(&self) -> Self::Word { - self.offset.get(BigEndian) - } - - fn size(&self) -> Self::Word { - self.size.get(BigEndian) - } - - fn align(&self) -> u32 { - self.align.get(BigEndian) - } -} - -impl FatArch for FatArch64 { - type Word = u64; - - fn cputype(&self) -> u32 { - self.cputype.get(BigEndian) - } - - fn cpusubtype(&self) -> u32 { - self.cpusubtype.get(BigEndian) - } - - fn offset(&self) -> Self::Word { - self.offset.get(BigEndian) - } - - fn size(&self) -> Self::Word { - self.size.get(BigEndian) - } - - fn align(&self) -> u32 { - self.align.get(BigEndian) - } -} diff --git a/vendor/object/src/read/macho/file.rs b/vendor/object/src/read/macho/file.rs deleted file mode 100644 index 0e04477..0000000 --- a/vendor/object/src/read/macho/file.rs +++ /dev/null @@ -1,781 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; -use core::{mem, str}; - -use crate::read::{ - self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator, - Object, ObjectComdat, ObjectKind, ObjectMap, ObjectSection, ReadError, ReadRef, Result, - SectionIndex, SubArchitecture, SymbolIndex, -}; -use crate::{endian, macho, BigEndian, ByteString, Endian, Endianness, Pod}; - -use super::{ - DyldCacheImage, LoadCommandIterator, MachOSection, MachOSectionInternal, MachOSectionIterator, - MachOSegment, MachOSegmentInternal, MachOSegmentIterator, MachOSymbol, MachOSymbolIterator, - MachOSymbolTable, Nlist, Section, Segment, SymbolTable, -}; - -/// A 32-bit Mach-O object file. -/// -/// This is a file that starts with [`macho::MachHeader32`], and corresponds -/// to [`crate::FileKind::MachO32`]. -pub type MachOFile32<'data, Endian = Endianness, R = &'data [u8]> = - MachOFile<'data, macho::MachHeader32, R>; -/// A 64-bit Mach-O object file. -/// -/// This is a file that starts with [`macho::MachHeader64`], and corresponds -/// to [`crate::FileKind::MachO64`]. -pub type MachOFile64<'data, Endian = Endianness, R = &'data [u8]> = - MachOFile<'data, macho::MachHeader64, R>; - -/// A partially parsed Mach-O file. -/// -/// Most of the functionality of this type is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct MachOFile<'data, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) endian: Mach::Endian, - pub(super) data: R, - pub(super) header_offset: u64, - pub(super) header: &'data Mach, - pub(super) segments: Vec>, - pub(super) sections: Vec>, - pub(super) symbols: SymbolTable<'data, Mach, R>, -} - -impl<'data, Mach, R> MachOFile<'data, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - /// Parse the raw Mach-O file data. - pub fn parse(data: R) -> Result { - let header = Mach::parse(data, 0)?; - let endian = header.endian()?; - - // Build a list of segments and sections to make some operations more efficient. - let mut segments = Vec::new(); - let mut sections = Vec::new(); - let mut symbols = SymbolTable::default(); - if let Ok(mut commands) = header.load_commands(endian, data, 0) { - while let Ok(Some(command)) = commands.next() { - if let Some((segment, section_data)) = Mach::Segment::from_command(command)? { - let segment_index = segments.len(); - segments.push(MachOSegmentInternal { segment, data }); - for section in segment.sections(endian, section_data)? { - let index = SectionIndex(sections.len() + 1); - sections.push(MachOSectionInternal::parse(index, segment_index, section)); - } - } else if let Some(symtab) = command.symtab()? { - symbols = symtab.symbols(endian, data)?; - } - } - } - - Ok(MachOFile { - endian, - data, - header_offset: 0, - header, - segments, - sections, - symbols, - }) - } - - /// Parse the Mach-O file for the given image from the dyld shared cache. - /// This will read different sections from different subcaches, if necessary. - pub fn parse_dyld_cache_image<'cache, E: Endian>( - image: &DyldCacheImage<'data, 'cache, E, R>, - ) -> Result { - let (data, header_offset) = image.image_data_and_offset()?; - let header = Mach::parse(data, header_offset)?; - let endian = header.endian()?; - - // Build a list of sections to make some operations more efficient. - // Also build a list of segments, because we need to remember which ReadRef - // to read each section's data from. Only the DyldCache knows this information, - // and we won't have access to it once we've exited this function. - let mut segments = Vec::new(); - let mut sections = Vec::new(); - let mut linkedit_data: Option = None; - let mut symtab = None; - if let Ok(mut commands) = header.load_commands(endian, data, header_offset) { - while let Ok(Some(command)) = commands.next() { - if let Some((segment, section_data)) = Mach::Segment::from_command(command)? { - // Each segment can be stored in a different subcache. Get the segment's - // address and look it up in the cache mappings, to find the correct cache data. - let addr = segment.vmaddr(endian).into(); - let (data, _offset) = image - .cache - .data_and_offset_for_address(addr) - .read_error("Could not find segment data in dyld shared cache")?; - if segment.name() == macho::SEG_LINKEDIT.as_bytes() { - linkedit_data = Some(data); - } - let segment_index = segments.len(); - segments.push(MachOSegmentInternal { segment, data }); - - for section in segment.sections(endian, section_data)? { - let index = SectionIndex(sections.len() + 1); - sections.push(MachOSectionInternal::parse(index, segment_index, section)); - } - } else if let Some(st) = command.symtab()? { - symtab = Some(st); - } - } - } - - // The symbols are found in the __LINKEDIT segment, so make sure to read them from the - // correct subcache. - let symbols = match (symtab, linkedit_data) { - (Some(symtab), Some(linkedit_data)) => symtab.symbols(endian, linkedit_data)?, - _ => SymbolTable::default(), - }; - - Ok(MachOFile { - endian, - data, - header_offset, - header, - segments, - sections, - symbols, - }) - } - - /// Return the section at the given index. - #[inline] - pub(super) fn section_internal( - &self, - index: SectionIndex, - ) -> Result<&MachOSectionInternal<'data, Mach>> { - index - .0 - .checked_sub(1) - .and_then(|index| self.sections.get(index)) - .read_error("Invalid Mach-O section index") - } - - pub(super) fn segment_internal( - &self, - index: usize, - ) -> Result<&MachOSegmentInternal<'data, Mach, R>> { - self.segments - .get(index) - .read_error("Invalid Mach-O segment index") - } - - /// Returns the endianness. - pub fn endian(&self) -> Mach::Endian { - self.endian - } - - /// Returns the raw data. - pub fn data(&self) -> R { - self.data - } - - /// Returns the raw Mach-O file header. - pub fn raw_header(&self) -> &'data Mach { - self.header - } - - /// Return the `LC_BUILD_VERSION` load command if present. - pub fn build_version(&self) -> Result>> { - let mut commands = self - .header - .load_commands(self.endian, self.data, self.header_offset)?; - while let Some(command) = commands.next()? { - if let Some(build_version) = command.build_version()? { - return Ok(Some(build_version)); - } - } - Ok(None) - } -} - -impl<'data, Mach, R> read::private::Sealed for MachOFile<'data, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> Object<'data, 'file> for MachOFile<'data, Mach, R> -where - 'data: 'file, - Mach: MachHeader, - R: 'file + ReadRef<'data>, -{ - type Segment = MachOSegment<'data, 'file, Mach, R>; - type SegmentIterator = MachOSegmentIterator<'data, 'file, Mach, R>; - type Section = MachOSection<'data, 'file, Mach, R>; - type SectionIterator = MachOSectionIterator<'data, 'file, Mach, R>; - type Comdat = MachOComdat<'data, 'file, Mach, R>; - type ComdatIterator = MachOComdatIterator<'data, 'file, Mach, R>; - type Symbol = MachOSymbol<'data, 'file, Mach, R>; - type SymbolIterator = MachOSymbolIterator<'data, 'file, Mach, R>; - type SymbolTable = MachOSymbolTable<'data, 'file, Mach, R>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - fn architecture(&self) -> Architecture { - match self.header.cputype(self.endian) { - macho::CPU_TYPE_ARM => Architecture::Arm, - macho::CPU_TYPE_ARM64 => Architecture::Aarch64, - macho::CPU_TYPE_ARM64_32 => Architecture::Aarch64_Ilp32, - macho::CPU_TYPE_X86 => Architecture::I386, - macho::CPU_TYPE_X86_64 => Architecture::X86_64, - macho::CPU_TYPE_MIPS => Architecture::Mips, - macho::CPU_TYPE_POWERPC => Architecture::PowerPc, - macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64, - _ => Architecture::Unknown, - } - } - - fn sub_architecture(&self) -> Option { - match ( - self.header.cputype(self.endian), - self.header.cpusubtype(self.endian), - ) { - (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64E) => Some(SubArchitecture::Arm64E), - _ => None, - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - self.header.is_little_endian() - } - - #[inline] - fn is_64(&self) -> bool { - self.header.is_type_64() - } - - fn kind(&self) -> ObjectKind { - match self.header.filetype(self.endian) { - macho::MH_OBJECT => ObjectKind::Relocatable, - macho::MH_EXECUTE => ObjectKind::Executable, - macho::MH_CORE => ObjectKind::Core, - macho::MH_DYLIB => ObjectKind::Dynamic, - _ => ObjectKind::Unknown, - } - } - - fn segments(&'file self) -> MachOSegmentIterator<'data, 'file, Mach, R> { - MachOSegmentIterator { - file: self, - iter: self.segments.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - // Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg - // ".debug_info" to "__debug_info", and limit to 16 bytes total. - let system_name = if section_name.starts_with(b".") { - if section_name.len() > 15 { - Some(§ion_name[1..15]) - } else { - Some(§ion_name[1..]) - } - } else { - None - }; - let cmp_section_name = |section: &MachOSection<'data, 'file, Mach, R>| { - section - .name_bytes() - .map(|name| { - section_name == name - || system_name - .filter(|system_name| { - name.starts_with(b"__") && name[2..] == **system_name - }) - .is_some() - }) - .unwrap_or(false) - }; - - self.sections().find(cmp_section_name) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> Result> { - let internal = *self.section_internal(index)?; - Ok(MachOSection { - file: self, - internal, - }) - } - - fn sections(&'file self) -> MachOSectionIterator<'data, 'file, Mach, R> { - MachOSectionIterator { - file: self, - iter: self.sections.iter(), - } - } - - fn comdats(&'file self) -> MachOComdatIterator<'data, 'file, Mach, R> { - MachOComdatIterator { file: self } - } - - fn symbol_by_index( - &'file self, - index: SymbolIndex, - ) -> Result> { - let nlist = self.symbols.symbol(index.0)?; - MachOSymbol::new(self, index, nlist).read_error("Unsupported Mach-O symbol index") - } - - fn symbols(&'file self) -> MachOSymbolIterator<'data, 'file, Mach, R> { - MachOSymbolIterator { - file: self, - index: 0, - } - } - - #[inline] - fn symbol_table(&'file self) -> Option> { - Some(MachOSymbolTable { file: self }) - } - - fn dynamic_symbols(&'file self) -> MachOSymbolIterator<'data, 'file, Mach, R> { - MachOSymbolIterator { - file: self, - index: self.symbols.len(), - } - } - - #[inline] - fn dynamic_symbol_table(&'file self) -> Option> { - None - } - - fn object_map(&'file self) -> ObjectMap<'data> { - self.symbols.object_map(self.endian) - } - - fn imports(&self) -> Result>> { - let mut dysymtab = None; - let mut libraries = Vec::new(); - let twolevel = self.header.flags(self.endian) & macho::MH_TWOLEVEL != 0; - if twolevel { - libraries.push(&[][..]); - } - let mut commands = self - .header - .load_commands(self.endian, self.data, self.header_offset)?; - while let Some(command) = commands.next()? { - if let Some(command) = command.dysymtab()? { - dysymtab = Some(command); - } - if twolevel { - if let Some(dylib) = command.dylib()? { - libraries.push(command.string(self.endian, dylib.dylib.name)?); - } - } - } - - let mut imports = Vec::new(); - if let Some(dysymtab) = dysymtab { - let index = dysymtab.iundefsym.get(self.endian) as usize; - let number = dysymtab.nundefsym.get(self.endian) as usize; - for i in index..(index.wrapping_add(number)) { - let symbol = self.symbols.symbol(i)?; - let name = symbol.name(self.endian, self.symbols.strings())?; - let library = if twolevel { - libraries - .get(symbol.library_ordinal(self.endian) as usize) - .copied() - .read_error("Invalid Mach-O symbol library ordinal")? - } else { - &[] - }; - imports.push(Import { - name: ByteString(name), - library: ByteString(library), - }); - } - } - Ok(imports) - } - - fn exports(&self) -> Result>> { - let mut dysymtab = None; - let mut commands = self - .header - .load_commands(self.endian, self.data, self.header_offset)?; - while let Some(command) = commands.next()? { - if let Some(command) = command.dysymtab()? { - dysymtab = Some(command); - break; - } - } - - let mut exports = Vec::new(); - if let Some(dysymtab) = dysymtab { - let index = dysymtab.iextdefsym.get(self.endian) as usize; - let number = dysymtab.nextdefsym.get(self.endian) as usize; - for i in index..(index.wrapping_add(number)) { - let symbol = self.symbols.symbol(i)?; - let name = symbol.name(self.endian, self.symbols.strings())?; - let address = symbol.n_value(self.endian).into(); - exports.push(Export { - name: ByteString(name), - address, - }); - } - } - Ok(exports) - } - - #[inline] - fn dynamic_relocations(&'file self) -> Option { - None - } - - fn has_debug_symbols(&self) -> bool { - self.section_by_name(".debug_info").is_some() - } - - fn mach_uuid(&self) -> Result> { - self.header.uuid(self.endian, self.data, self.header_offset) - } - - fn relative_address_base(&self) -> u64 { - 0 - } - - fn entry(&self) -> u64 { - if let Ok(mut commands) = - self.header - .load_commands(self.endian, self.data, self.header_offset) - { - while let Ok(Some(command)) = commands.next() { - if let Ok(Some(command)) = command.entry_point() { - return command.entryoff.get(self.endian); - } - } - } - 0 - } - - fn flags(&self) -> FileFlags { - FileFlags::MachO { - flags: self.header.flags(self.endian), - } - } -} - -/// An iterator for the COMDAT section groups in a [`MachOFile64`]. -pub type MachOComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdatIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the COMDAT section groups in a [`MachOFile64`]. -pub type MachOComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdatIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the COMDAT section groups in a [`MachOFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct MachOComdatIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file MachOFile<'data, Mach, R>, -} - -impl<'data, 'file, Mach, R> Iterator for MachOComdatIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = MachOComdat<'data, 'file, Mach, R>; - - #[inline] - fn next(&mut self) -> Option { - None - } -} - -/// A COMDAT section group in a [`MachOFile32`]. -pub type MachOComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdat<'data, 'file, macho::MachHeader32, R>; - -/// A COMDAT section group in a [`MachOFile64`]. -pub type MachOComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdat<'data, 'file, macho::MachHeader64, R>; - -/// A COMDAT section group in a [`MachOFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct MachOComdat<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file MachOFile<'data, Mach, R>, -} - -impl<'data, 'file, Mach, R> read::private::Sealed for MachOComdat<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> ObjectComdat<'data> for MachOComdat<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type SectionIterator = MachOComdatSectionIterator<'data, 'file, Mach, R>; - - #[inline] - fn kind(&self) -> ComdatKind { - unreachable!(); - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - unreachable!(); - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - unreachable!(); - } - - #[inline] - fn name(&self) -> Result<&str> { - unreachable!(); - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - unreachable!(); - } -} - -/// An iterator for the sections in a COMDAT section group in a [`MachOFile32`]. -pub type MachOComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdatSectionIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the sections in a COMDAT section group in a [`MachOFile64`]. -pub type MachOComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOComdatSectionIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the sections in a COMDAT section group in a [`MachOFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct MachOComdatSectionIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file MachOFile<'data, Mach, R>, -} - -impl<'data, 'file, Mach, R> Iterator for MachOComdatSectionIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option { - None - } -} - -/// A trait for generic access to [`macho::MachHeader32`] and [`macho::MachHeader64`]. -#[allow(missing_docs)] -pub trait MachHeader: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - type Segment: Segment; - type Section: Section; - type Nlist: Nlist; - - /// Return true if this type is a 64-bit header. - /// - /// This is a property of the type, not a value in the header data. - fn is_type_64(&self) -> bool; - - /// Return true if the `magic` field signifies big-endian. - fn is_big_endian(&self) -> bool; - - /// Return true if the `magic` field signifies little-endian. - fn is_little_endian(&self) -> bool; - - fn magic(&self) -> u32; - fn cputype(&self, endian: Self::Endian) -> u32; - fn cpusubtype(&self, endian: Self::Endian) -> u32; - fn filetype(&self, endian: Self::Endian) -> u32; - fn ncmds(&self, endian: Self::Endian) -> u32; - fn sizeofcmds(&self, endian: Self::Endian) -> u32; - fn flags(&self, endian: Self::Endian) -> u32; - - // Provided methods. - - /// Read the file header. - /// - /// Also checks that the magic field in the file header is a supported format. - fn parse<'data, R: ReadRef<'data>>(data: R, offset: u64) -> read::Result<&'data Self> { - let header = data - .read_at::(offset) - .read_error("Invalid Mach-O header size or alignment")?; - if !header.is_supported() { - return Err(Error("Unsupported Mach-O header")); - } - Ok(header) - } - - fn is_supported(&self) -> bool { - self.is_little_endian() || self.is_big_endian() - } - - fn endian(&self) -> Result { - Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported Mach-O endian") - } - - fn load_commands<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - header_offset: u64, - ) -> Result> { - let data = data - .read_bytes_at( - header_offset + mem::size_of::() as u64, - self.sizeofcmds(endian).into(), - ) - .read_error("Invalid Mach-O load command table size")?; - Ok(LoadCommandIterator::new(endian, data, self.ncmds(endian))) - } - - /// Return the UUID from the `LC_UUID` load command, if one is present. - fn uuid<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - header_offset: u64, - ) -> Result> { - let mut commands = self.load_commands(endian, data, header_offset)?; - while let Some(command) = commands.next()? { - if let Ok(Some(uuid)) = command.uuid() { - return Ok(Some(uuid.uuid)); - } - } - Ok(None) - } -} - -impl MachHeader for macho::MachHeader32 { - type Word = u32; - type Endian = Endian; - type Segment = macho::SegmentCommand32; - type Section = macho::Section32; - type Nlist = macho::Nlist32; - - fn is_type_64(&self) -> bool { - false - } - - fn is_big_endian(&self) -> bool { - self.magic() == macho::MH_MAGIC - } - - fn is_little_endian(&self) -> bool { - self.magic() == macho::MH_CIGAM - } - - fn magic(&self) -> u32 { - self.magic.get(BigEndian) - } - - fn cputype(&self, endian: Self::Endian) -> u32 { - self.cputype.get(endian) - } - - fn cpusubtype(&self, endian: Self::Endian) -> u32 { - self.cpusubtype.get(endian) - } - - fn filetype(&self, endian: Self::Endian) -> u32 { - self.filetype.get(endian) - } - - fn ncmds(&self, endian: Self::Endian) -> u32 { - self.ncmds.get(endian) - } - - fn sizeofcmds(&self, endian: Self::Endian) -> u32 { - self.sizeofcmds.get(endian) - } - - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} - -impl MachHeader for macho::MachHeader64 { - type Word = u64; - type Endian = Endian; - type Segment = macho::SegmentCommand64; - type Section = macho::Section64; - type Nlist = macho::Nlist64; - - fn is_type_64(&self) -> bool { - true - } - - fn is_big_endian(&self) -> bool { - self.magic() == macho::MH_MAGIC_64 - } - - fn is_little_endian(&self) -> bool { - self.magic() == macho::MH_CIGAM_64 - } - - fn magic(&self) -> u32 { - self.magic.get(BigEndian) - } - - fn cputype(&self, endian: Self::Endian) -> u32 { - self.cputype.get(endian) - } - - fn cpusubtype(&self, endian: Self::Endian) -> u32 { - self.cpusubtype.get(endian) - } - - fn filetype(&self, endian: Self::Endian) -> u32 { - self.filetype.get(endian) - } - - fn ncmds(&self, endian: Self::Endian) -> u32 { - self.ncmds.get(endian) - } - - fn sizeofcmds(&self, endian: Self::Endian) -> u32 { - self.sizeofcmds.get(endian) - } - - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} diff --git a/vendor/object/src/read/macho/load_command.rs b/vendor/object/src/read/macho/load_command.rs deleted file mode 100644 index 7225fbd..0000000 --- a/vendor/object/src/read/macho/load_command.rs +++ /dev/null @@ -1,382 +0,0 @@ -use core::marker::PhantomData; -use core::mem; - -use crate::endian::Endian; -use crate::macho; -use crate::pod::Pod; -use crate::read::macho::{MachHeader, SymbolTable}; -use crate::read::{Bytes, Error, ReadError, ReadRef, Result, StringTable}; - -/// An iterator for the load commands from a [`MachHeader`]. -#[derive(Debug, Default, Clone, Copy)] -pub struct LoadCommandIterator<'data, E: Endian> { - endian: E, - data: Bytes<'data>, - ncmds: u32, -} - -impl<'data, E: Endian> LoadCommandIterator<'data, E> { - pub(super) fn new(endian: E, data: &'data [u8], ncmds: u32) -> Self { - LoadCommandIterator { - endian, - data: Bytes(data), - ncmds, - } - } - - /// Return the next load command. - pub fn next(&mut self) -> Result>> { - if self.ncmds == 0 { - return Ok(None); - } - let header = self - .data - .read_at::>(0) - .read_error("Invalid Mach-O load command header")?; - let cmd = header.cmd.get(self.endian); - let cmdsize = header.cmdsize.get(self.endian) as usize; - if cmdsize < mem::size_of::>() { - return Err(Error("Invalid Mach-O load command size")); - } - let data = self - .data - .read_bytes(cmdsize) - .read_error("Invalid Mach-O load command size")?; - self.ncmds -= 1; - Ok(Some(LoadCommandData { - cmd, - data, - marker: Default::default(), - })) - } -} - -/// The data for a [`macho::LoadCommand`]. -#[derive(Debug, Clone, Copy)] -pub struct LoadCommandData<'data, E: Endian> { - cmd: u32, - // Includes the header. - data: Bytes<'data>, - marker: PhantomData, -} - -impl<'data, E: Endian> LoadCommandData<'data, E> { - /// Return the `cmd` field of the [`macho::LoadCommand`]. - /// - /// This is one of the `LC_` constants. - pub fn cmd(&self) -> u32 { - self.cmd - } - - /// Return the `cmdsize` field of the [`macho::LoadCommand`]. - pub fn cmdsize(&self) -> u32 { - self.data.len() as u32 - } - - /// Parse the data as the given type. - #[inline] - pub fn data(&self) -> Result<&'data T> { - self.data - .read_at(0) - .read_error("Invalid Mach-O command size") - } - - /// Raw bytes of this [`macho::LoadCommand`] structure. - pub fn raw_data(&self) -> &'data [u8] { - self.data.0 - } - - /// Parse a load command string value. - /// - /// Strings used by load commands are specified by offsets that are - /// relative to the load command header. - pub fn string(&self, endian: E, s: macho::LcStr) -> Result<&'data [u8]> { - self.data - .read_string_at(s.offset.get(endian) as usize) - .read_error("Invalid load command string offset") - } - - /// Parse the command data according to the `cmd` field. - pub fn variant(&self) -> Result> { - Ok(match self.cmd { - macho::LC_SEGMENT => { - let mut data = self.data; - let segment = data.read().read_error("Invalid Mach-O command size")?; - LoadCommandVariant::Segment32(segment, data.0) - } - macho::LC_SYMTAB => LoadCommandVariant::Symtab(self.data()?), - macho::LC_THREAD | macho::LC_UNIXTHREAD => { - let mut data = self.data; - let thread = data.read().read_error("Invalid Mach-O command size")?; - LoadCommandVariant::Thread(thread, data.0) - } - macho::LC_DYSYMTAB => LoadCommandVariant::Dysymtab(self.data()?), - macho::LC_LOAD_DYLIB - | macho::LC_LOAD_WEAK_DYLIB - | macho::LC_REEXPORT_DYLIB - | macho::LC_LAZY_LOAD_DYLIB - | macho::LC_LOAD_UPWARD_DYLIB => LoadCommandVariant::Dylib(self.data()?), - macho::LC_ID_DYLIB => LoadCommandVariant::IdDylib(self.data()?), - macho::LC_LOAD_DYLINKER => LoadCommandVariant::LoadDylinker(self.data()?), - macho::LC_ID_DYLINKER => LoadCommandVariant::IdDylinker(self.data()?), - macho::LC_PREBOUND_DYLIB => LoadCommandVariant::PreboundDylib(self.data()?), - macho::LC_ROUTINES => LoadCommandVariant::Routines32(self.data()?), - macho::LC_SUB_FRAMEWORK => LoadCommandVariant::SubFramework(self.data()?), - macho::LC_SUB_UMBRELLA => LoadCommandVariant::SubUmbrella(self.data()?), - macho::LC_SUB_CLIENT => LoadCommandVariant::SubClient(self.data()?), - macho::LC_SUB_LIBRARY => LoadCommandVariant::SubLibrary(self.data()?), - macho::LC_TWOLEVEL_HINTS => LoadCommandVariant::TwolevelHints(self.data()?), - macho::LC_PREBIND_CKSUM => LoadCommandVariant::PrebindCksum(self.data()?), - macho::LC_SEGMENT_64 => { - let mut data = self.data; - let segment = data.read().read_error("Invalid Mach-O command size")?; - LoadCommandVariant::Segment64(segment, data.0) - } - macho::LC_ROUTINES_64 => LoadCommandVariant::Routines64(self.data()?), - macho::LC_UUID => LoadCommandVariant::Uuid(self.data()?), - macho::LC_RPATH => LoadCommandVariant::Rpath(self.data()?), - macho::LC_CODE_SIGNATURE - | macho::LC_SEGMENT_SPLIT_INFO - | macho::LC_FUNCTION_STARTS - | macho::LC_DATA_IN_CODE - | macho::LC_DYLIB_CODE_SIGN_DRS - | macho::LC_LINKER_OPTIMIZATION_HINT - | macho::LC_DYLD_EXPORTS_TRIE - | macho::LC_DYLD_CHAINED_FIXUPS => LoadCommandVariant::LinkeditData(self.data()?), - macho::LC_ENCRYPTION_INFO => LoadCommandVariant::EncryptionInfo32(self.data()?), - macho::LC_DYLD_INFO | macho::LC_DYLD_INFO_ONLY => { - LoadCommandVariant::DyldInfo(self.data()?) - } - macho::LC_VERSION_MIN_MACOSX - | macho::LC_VERSION_MIN_IPHONEOS - | macho::LC_VERSION_MIN_TVOS - | macho::LC_VERSION_MIN_WATCHOS => LoadCommandVariant::VersionMin(self.data()?), - macho::LC_DYLD_ENVIRONMENT => LoadCommandVariant::DyldEnvironment(self.data()?), - macho::LC_MAIN => LoadCommandVariant::EntryPoint(self.data()?), - macho::LC_SOURCE_VERSION => LoadCommandVariant::SourceVersion(self.data()?), - macho::LC_ENCRYPTION_INFO_64 => LoadCommandVariant::EncryptionInfo64(self.data()?), - macho::LC_LINKER_OPTION => LoadCommandVariant::LinkerOption(self.data()?), - macho::LC_NOTE => LoadCommandVariant::Note(self.data()?), - macho::LC_BUILD_VERSION => LoadCommandVariant::BuildVersion(self.data()?), - macho::LC_FILESET_ENTRY => LoadCommandVariant::FilesetEntry(self.data()?), - _ => LoadCommandVariant::Other, - }) - } - - /// Try to parse this command as a [`macho::SegmentCommand32`]. - /// - /// Returns the segment command and the data containing the sections. - pub fn segment_32(self) -> Result, &'data [u8])>> { - if self.cmd == macho::LC_SEGMENT { - let mut data = self.data; - let segment = data.read().read_error("Invalid Mach-O command size")?; - Ok(Some((segment, data.0))) - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::SymtabCommand`]. - /// - /// Returns the segment command and the data containing the sections. - pub fn symtab(self) -> Result>> { - if self.cmd == macho::LC_SYMTAB { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::DysymtabCommand`]. - pub fn dysymtab(self) -> Result>> { - if self.cmd == macho::LC_DYSYMTAB { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::DylibCommand`]. - pub fn dylib(self) -> Result>> { - if self.cmd == macho::LC_LOAD_DYLIB - || self.cmd == macho::LC_LOAD_WEAK_DYLIB - || self.cmd == macho::LC_REEXPORT_DYLIB - || self.cmd == macho::LC_LAZY_LOAD_DYLIB - || self.cmd == macho::LC_LOAD_UPWARD_DYLIB - { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::UuidCommand`]. - pub fn uuid(self) -> Result>> { - if self.cmd == macho::LC_UUID { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::SegmentCommand64`]. - pub fn segment_64(self) -> Result, &'data [u8])>> { - if self.cmd == macho::LC_SEGMENT_64 { - let mut data = self.data; - let command = data.read().read_error("Invalid Mach-O command size")?; - Ok(Some((command, data.0))) - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::DyldInfoCommand`]. - pub fn dyld_info(self) -> Result>> { - if self.cmd == macho::LC_DYLD_INFO || self.cmd == macho::LC_DYLD_INFO_ONLY { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as an [`macho::EntryPointCommand`]. - pub fn entry_point(self) -> Result>> { - if self.cmd == macho::LC_MAIN { - Some(self.data()).transpose() - } else { - Ok(None) - } - } - - /// Try to parse this command as a [`macho::BuildVersionCommand`]. - pub fn build_version(self) -> Result>> { - if self.cmd == macho::LC_BUILD_VERSION { - Some(self.data()).transpose() - } else { - Ok(None) - } - } -} - -/// A [`macho::LoadCommand`] that has been interpreted according to its `cmd` field. -#[derive(Debug, Clone, Copy)] -#[non_exhaustive] -pub enum LoadCommandVariant<'data, E: Endian> { - /// `LC_SEGMENT` - Segment32(&'data macho::SegmentCommand32, &'data [u8]), - /// `LC_SYMTAB` - Symtab(&'data macho::SymtabCommand), - // obsolete: `LC_SYMSEG` - //Symseg(&'data macho::SymsegCommand), - /// `LC_THREAD` or `LC_UNIXTHREAD` - Thread(&'data macho::ThreadCommand, &'data [u8]), - // obsolete: `LC_IDFVMLIB` or `LC_LOADFVMLIB` - //Fvmlib(&'data macho::FvmlibCommand), - // obsolete: `LC_IDENT` - //Ident(&'data macho::IdentCommand), - // internal: `LC_FVMFILE` - //Fvmfile(&'data macho::FvmfileCommand), - // internal: `LC_PREPAGE` - /// `LC_DYSYMTAB` - Dysymtab(&'data macho::DysymtabCommand), - /// `LC_LOAD_DYLIB`, `LC_LOAD_WEAK_DYLIB`, `LC_REEXPORT_DYLIB`, - /// `LC_LAZY_LOAD_DYLIB`, or `LC_LOAD_UPWARD_DYLIB` - Dylib(&'data macho::DylibCommand), - /// `LC_ID_DYLIB` - IdDylib(&'data macho::DylibCommand), - /// `LC_LOAD_DYLINKER` - LoadDylinker(&'data macho::DylinkerCommand), - /// `LC_ID_DYLINKER` - IdDylinker(&'data macho::DylinkerCommand), - /// `LC_PREBOUND_DYLIB` - PreboundDylib(&'data macho::PreboundDylibCommand), - /// `LC_ROUTINES` - Routines32(&'data macho::RoutinesCommand32), - /// `LC_SUB_FRAMEWORK` - SubFramework(&'data macho::SubFrameworkCommand), - /// `LC_SUB_UMBRELLA` - SubUmbrella(&'data macho::SubUmbrellaCommand), - /// `LC_SUB_CLIENT` - SubClient(&'data macho::SubClientCommand), - /// `LC_SUB_LIBRARY` - SubLibrary(&'data macho::SubLibraryCommand), - /// `LC_TWOLEVEL_HINTS` - TwolevelHints(&'data macho::TwolevelHintsCommand), - /// `LC_PREBIND_CKSUM` - PrebindCksum(&'data macho::PrebindCksumCommand), - /// `LC_SEGMENT_64` - Segment64(&'data macho::SegmentCommand64, &'data [u8]), - /// `LC_ROUTINES_64` - Routines64(&'data macho::RoutinesCommand64), - /// `LC_UUID` - Uuid(&'data macho::UuidCommand), - /// `LC_RPATH` - Rpath(&'data macho::RpathCommand), - /// `LC_CODE_SIGNATURE`, `LC_SEGMENT_SPLIT_INFO`, `LC_FUNCTION_STARTS`, - /// `LC_DATA_IN_CODE`, `LC_DYLIB_CODE_SIGN_DRS`, `LC_LINKER_OPTIMIZATION_HINT`, - /// `LC_DYLD_EXPORTS_TRIE`, or `LC_DYLD_CHAINED_FIXUPS`. - LinkeditData(&'data macho::LinkeditDataCommand), - /// `LC_ENCRYPTION_INFO` - EncryptionInfo32(&'data macho::EncryptionInfoCommand32), - /// `LC_DYLD_INFO` or `LC_DYLD_INFO_ONLY` - DyldInfo(&'data macho::DyldInfoCommand), - /// `LC_VERSION_MIN_MACOSX`, `LC_VERSION_MIN_IPHONEOS`, `LC_VERSION_MIN_WATCHOS`, - /// or `LC_VERSION_MIN_TVOS` - VersionMin(&'data macho::VersionMinCommand), - /// `LC_DYLD_ENVIRONMENT` - DyldEnvironment(&'data macho::DylinkerCommand), - /// `LC_MAIN` - EntryPoint(&'data macho::EntryPointCommand), - /// `LC_SOURCE_VERSION` - SourceVersion(&'data macho::SourceVersionCommand), - /// `LC_ENCRYPTION_INFO_64` - EncryptionInfo64(&'data macho::EncryptionInfoCommand64), - /// `LC_LINKER_OPTION` - LinkerOption(&'data macho::LinkerOptionCommand), - /// `LC_NOTE` - Note(&'data macho::NoteCommand), - /// `LC_BUILD_VERSION` - BuildVersion(&'data macho::BuildVersionCommand), - /// `LC_FILESET_ENTRY` - FilesetEntry(&'data macho::FilesetEntryCommand), - /// An unrecognized or obsolete load command. - Other, -} - -impl macho::SymtabCommand { - /// Return the symbol table that this command references. - pub fn symbols<'data, Mach: MachHeader, R: ReadRef<'data>>( - &self, - endian: E, - data: R, - ) -> Result> { - let symbols = data - .read_slice_at( - self.symoff.get(endian).into(), - self.nsyms.get(endian) as usize, - ) - .read_error("Invalid Mach-O symbol table offset or size")?; - let str_start: u64 = self.stroff.get(endian).into(); - let str_end = str_start - .checked_add(self.strsize.get(endian).into()) - .read_error("Invalid Mach-O string table length")?; - let strings = StringTable::new(data, str_start, str_end); - Ok(SymbolTable::new(symbols, strings)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::LittleEndian; - - #[test] - fn cmd_size_invalid() { - let mut commands = LoadCommandIterator::new(LittleEndian, &[0; 8], 10); - assert!(commands.next().is_err()); - let mut commands = LoadCommandIterator::new(LittleEndian, &[0, 0, 0, 0, 7, 0, 0, 0, 0], 10); - assert!(commands.next().is_err()); - let mut commands = LoadCommandIterator::new(LittleEndian, &[0, 0, 0, 0, 8, 0, 0, 0, 0], 10); - assert!(commands.next().is_ok()); - } -} diff --git a/vendor/object/src/read/macho/mod.rs b/vendor/object/src/read/macho/mod.rs deleted file mode 100644 index ab51ff3..0000000 --- a/vendor/object/src/read/macho/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! Support for reading Mach-O files. -//! -//! Traits are used to abstract over the difference between 32-bit and 64-bit Mach-O -//! files. The primary trait for this is [`MachHeader`]. -//! -//! ## High level API -//! -//! [`MachOFile`] implements the [`Object`](crate::read::Object) trait for Mach-O files. -//! [`MachOFile`] is parameterised by [`MachHeader`] to allow reading both 32-bit and -//! 64-bit Mach-O files. There are type aliases for these parameters ([`MachOFile32`] and -//! [`MachOFile64`]). -//! -//! ## Low level API -//! -//! The [`MachHeader`] trait can be directly used to parse both [`macho::MachHeader32`] -//! and [`macho::MachHeader64`]. Additionally, [`FatHeader`] and the [`FatArch`] trait -//! can be used to iterate images in multi-architecture binaries, and [`DyldCache`] can -//! be used to locate images in a dyld shared cache. -//! -//! ### Example for low level API -//! ```no_run -//! use object::macho; -//! use object::read::macho::{MachHeader, Nlist}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each symbol. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let header = macho::MachHeader64::::parse(&*data, 0)?; -//! let endian = header.endian()?; -//! let mut commands = header.load_commands(endian, &*data, 0)?; -//! while let Some(command) = commands.next()? { -//! if let Some(symtab_command) = command.symtab()? { -//! let symbols = symtab_command.symbols::, _>(endian, &*data)?; -//! for symbol in symbols.iter() { -//! let name = symbol.name(endian, symbols.strings())?; -//! println!("{}", String::from_utf8_lossy(name)); -//! } -//! } -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::macho; - -mod dyld_cache; -pub use dyld_cache::*; - -mod fat; -pub use fat::*; - -mod file; -pub use file::*; - -mod load_command; -pub use load_command::*; - -mod segment; -pub use segment::*; - -mod section; -pub use section::*; - -mod symbol; -pub use symbol::*; - -mod relocation; -pub use relocation::*; diff --git a/vendor/object/src/read/macho/relocation.rs b/vendor/object/src/read/macho/relocation.rs deleted file mode 100644 index 709f1a4..0000000 --- a/vendor/object/src/read/macho/relocation.rs +++ /dev/null @@ -1,158 +0,0 @@ -use core::{fmt, slice}; - -use crate::endian::Endianness; -use crate::macho; -use crate::read::{ - ReadRef, Relocation, RelocationEncoding, RelocationKind, RelocationTarget, SectionIndex, - SymbolIndex, -}; - -use super::{MachHeader, MachOFile}; - -/// An iterator for the relocations in a [`MachOSection32`](super::MachOSection32). -pub type MachORelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachORelocationIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the relocations in a [`MachOSection64`](super::MachOSection64). -pub type MachORelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachORelocationIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the relocations in a [`MachOSection`](super::MachOSection). -pub struct MachORelocationIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, - pub(super) relocations: slice::Iter<'data, macho::Relocation>, -} - -impl<'data, 'file, Mach, R> Iterator for MachORelocationIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - let mut paired_addend = 0; - loop { - let reloc = self.relocations.next()?; - let endian = self.file.endian; - let cputype = self.file.header.cputype(endian); - if reloc.r_scattered(endian, cputype) { - // FIXME: handle scattered relocations - // We need to add `RelocationTarget::Address` for this. - continue; - } - let reloc = reloc.info(self.file.endian); - let mut encoding = RelocationEncoding::Generic; - let kind = match cputype { - macho::CPU_TYPE_ARM => match (reloc.r_type, reloc.r_pcrel) { - (macho::ARM_RELOC_VANILLA, false) => RelocationKind::Absolute, - _ => RelocationKind::MachO { - value: reloc.r_type, - relative: reloc.r_pcrel, - }, - }, - macho::CPU_TYPE_ARM64 | macho::CPU_TYPE_ARM64_32 => { - match (reloc.r_type, reloc.r_pcrel) { - (macho::ARM64_RELOC_UNSIGNED, false) => RelocationKind::Absolute, - (macho::ARM64_RELOC_ADDEND, _) => { - paired_addend = i64::from(reloc.r_symbolnum) - .wrapping_shl(64 - 24) - .wrapping_shr(64 - 24); - continue; - } - _ => RelocationKind::MachO { - value: reloc.r_type, - relative: reloc.r_pcrel, - }, - } - } - macho::CPU_TYPE_X86 => match (reloc.r_type, reloc.r_pcrel) { - (macho::GENERIC_RELOC_VANILLA, false) => RelocationKind::Absolute, - _ => RelocationKind::MachO { - value: reloc.r_type, - relative: reloc.r_pcrel, - }, - }, - macho::CPU_TYPE_X86_64 => match (reloc.r_type, reloc.r_pcrel) { - (macho::X86_64_RELOC_UNSIGNED, false) => RelocationKind::Absolute, - (macho::X86_64_RELOC_SIGNED, true) => { - encoding = RelocationEncoding::X86RipRelative; - RelocationKind::Relative - } - (macho::X86_64_RELOC_BRANCH, true) => { - encoding = RelocationEncoding::X86Branch; - RelocationKind::Relative - } - (macho::X86_64_RELOC_GOT, true) => RelocationKind::GotRelative, - (macho::X86_64_RELOC_GOT_LOAD, true) => { - encoding = RelocationEncoding::X86RipRelativeMovq; - RelocationKind::GotRelative - } - _ => RelocationKind::MachO { - value: reloc.r_type, - relative: reloc.r_pcrel, - }, - }, - _ => RelocationKind::MachO { - value: reloc.r_type, - relative: reloc.r_pcrel, - }, - }; - let size = 8 << reloc.r_length; - let target = if reloc.r_extern { - RelocationTarget::Symbol(SymbolIndex(reloc.r_symbolnum as usize)) - } else { - RelocationTarget::Section(SectionIndex(reloc.r_symbolnum as usize)) - }; - let implicit_addend = paired_addend == 0; - let mut addend = paired_addend; - if reloc.r_pcrel { - // For PC relative relocations on some architectures, the - // addend does not include the offset required due to the - // PC being different from the place of the relocation. - // This differs from other file formats, so adjust the - // addend here to account for this. - match cputype { - macho::CPU_TYPE_X86 => { - addend -= 1 << reloc.r_length; - } - macho::CPU_TYPE_X86_64 => { - addend -= 1 << reloc.r_length; - match reloc.r_type { - macho::X86_64_RELOC_SIGNED_1 => addend -= 1, - macho::X86_64_RELOC_SIGNED_2 => addend -= 2, - macho::X86_64_RELOC_SIGNED_4 => addend -= 4, - _ => {} - } - } - // TODO: maybe missing support for some architectures and relocations - _ => {} - } - } - return Some(( - reloc.r_address as u64, - Relocation { - kind, - encoding, - size, - target, - addend, - implicit_addend, - }, - )); - } - } -} - -impl<'data, 'file, Mach, R> fmt::Debug for MachORelocationIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MachORelocationIterator").finish() - } -} diff --git a/vendor/object/src/read/macho/section.rs b/vendor/object/src/read/macho/section.rs deleted file mode 100644 index 7c79123..0000000 --- a/vendor/object/src/read/macho/section.rs +++ /dev/null @@ -1,389 +0,0 @@ -use core::fmt::Debug; -use core::{fmt, result, slice, str}; - -use crate::endian::{self, Endianness}; -use crate::macho; -use crate::pod::Pod; -use crate::read::{ - self, CompressedData, CompressedFileRange, ObjectSection, ReadError, ReadRef, Result, - SectionFlags, SectionIndex, SectionKind, -}; - -use super::{MachHeader, MachOFile, MachORelocationIterator}; - -/// An iterator for the sections in a [`MachOFile32`](super::MachOFile32). -pub type MachOSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSectionIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the sections in a [`MachOFile64`](super::MachOFile64). -pub type MachOSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSectionIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the sections in a [`MachOFile`]. -pub struct MachOSectionIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, - pub(super) iter: slice::Iter<'file, MachOSectionInternal<'data, Mach>>, -} - -impl<'data, 'file, Mach, R> fmt::Debug for MachOSectionIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // It's painful to do much better than this - f.debug_struct("MachOSectionIterator").finish() - } -} - -impl<'data, 'file, Mach, R> Iterator for MachOSectionIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = MachOSection<'data, 'file, Mach, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|&internal| MachOSection { - file: self.file, - internal, - }) - } -} - -/// A section in a [`MachOFile32`](super::MachOFile32). -pub type MachOSection32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSection<'data, 'file, macho::MachHeader32, R>; -/// A section in a [`MachOFile64`](super::MachOFile64). -pub type MachOSection64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSection<'data, 'file, macho::MachHeader64, R>; - -/// A section in a [`MachOFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct MachOSection<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, - pub(super) internal: MachOSectionInternal<'data, Mach>, -} - -impl<'data, 'file, Mach, R> MachOSection<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - fn bytes(&self) -> Result<&'data [u8]> { - let segment_index = self.internal.segment_index; - let segment = self.file.segment_internal(segment_index)?; - self.internal - .section - .data(self.file.endian, segment.data) - .read_error("Invalid Mach-O section size or offset") - } -} - -impl<'data, 'file, Mach, R> read::private::Sealed for MachOSection<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> ObjectSection<'data> for MachOSection<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type RelocationIterator = MachORelocationIterator<'data, 'file, Mach, R>; - - #[inline] - fn index(&self) -> SectionIndex { - self.internal.index - } - - #[inline] - fn address(&self) -> u64 { - self.internal.section.addr(self.file.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - self.internal.section.size(self.file.endian).into() - } - - #[inline] - fn align(&self) -> u64 { - let align = self.internal.section.align(self.file.endian); - if align < 64 { - 1 << align - } else { - 0 - } - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - self.internal.section.file_range(self.file.endian) - } - - #[inline] - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn compressed_file_range(&self) -> Result { - Ok(CompressedFileRange::none(self.file_range())) - } - - #[inline] - fn compressed_data(&self) -> Result> { - self.data().map(CompressedData::none) - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - Ok(self.internal.section.name()) - } - - #[inline] - fn name(&self) -> Result<&str> { - str::from_utf8(self.internal.section.name()) - .ok() - .read_error("Non UTF-8 Mach-O section name") - } - - #[inline] - fn segment_name_bytes(&self) -> Result> { - Ok(Some(self.internal.section.segment_name())) - } - - #[inline] - fn segment_name(&self) -> Result> { - Ok(Some( - str::from_utf8(self.internal.section.segment_name()) - .ok() - .read_error("Non UTF-8 Mach-O segment name")?, - )) - } - - fn kind(&self) -> SectionKind { - self.internal.kind - } - - fn relocations(&self) -> MachORelocationIterator<'data, 'file, Mach, R> { - MachORelocationIterator { - file: self.file, - relocations: self - .internal - .section - .relocations(self.file.endian, self.file.data) - .unwrap_or(&[]) - .iter(), - } - } - - fn flags(&self) -> SectionFlags { - SectionFlags::MachO { - flags: self.internal.section.flags(self.file.endian), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub(super) struct MachOSectionInternal<'data, Mach: MachHeader> { - pub index: SectionIndex, - pub segment_index: usize, - pub kind: SectionKind, - pub section: &'data Mach::Section, -} - -impl<'data, Mach: MachHeader> MachOSectionInternal<'data, Mach> { - pub(super) fn parse( - index: SectionIndex, - segment_index: usize, - section: &'data Mach::Section, - ) -> Self { - // TODO: we don't validate flags, should we? - let kind = match (section.segment_name(), section.name()) { - (b"__TEXT", b"__text") => SectionKind::Text, - (b"__TEXT", b"__const") => SectionKind::ReadOnlyData, - (b"__TEXT", b"__cstring") => SectionKind::ReadOnlyString, - (b"__TEXT", b"__literal4") => SectionKind::ReadOnlyData, - (b"__TEXT", b"__literal8") => SectionKind::ReadOnlyData, - (b"__TEXT", b"__literal16") => SectionKind::ReadOnlyData, - (b"__TEXT", b"__eh_frame") => SectionKind::ReadOnlyData, - (b"__TEXT", b"__gcc_except_tab") => SectionKind::ReadOnlyData, - (b"__DATA", b"__data") => SectionKind::Data, - (b"__DATA", b"__const") => SectionKind::ReadOnlyData, - (b"__DATA", b"__bss") => SectionKind::UninitializedData, - (b"__DATA", b"__common") => SectionKind::Common, - (b"__DATA", b"__thread_data") => SectionKind::Tls, - (b"__DATA", b"__thread_bss") => SectionKind::UninitializedTls, - (b"__DATA", b"__thread_vars") => SectionKind::TlsVariables, - (b"__DWARF", _) => SectionKind::Debug, - _ => SectionKind::Unknown, - }; - MachOSectionInternal { - index, - segment_index, - kind, - section, - } - } -} - -/// A trait for generic access to [`macho::Section32`] and [`macho::Section64`]. -#[allow(missing_docs)] -pub trait Section: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - - fn sectname(&self) -> &[u8; 16]; - fn segname(&self) -> &[u8; 16]; - fn addr(&self, endian: Self::Endian) -> Self::Word; - fn size(&self, endian: Self::Endian) -> Self::Word; - fn offset(&self, endian: Self::Endian) -> u32; - fn align(&self, endian: Self::Endian) -> u32; - fn reloff(&self, endian: Self::Endian) -> u32; - fn nreloc(&self, endian: Self::Endian) -> u32; - fn flags(&self, endian: Self::Endian) -> u32; - - /// Return the `sectname` bytes up until the null terminator. - fn name(&self) -> &[u8] { - let sectname = &self.sectname()[..]; - match memchr::memchr(b'\0', sectname) { - Some(end) => §name[..end], - None => sectname, - } - } - - /// Return the `segname` bytes up until the null terminator. - fn segment_name(&self) -> &[u8] { - let segname = &self.segname()[..]; - match memchr::memchr(b'\0', segname) { - Some(end) => &segname[..end], - None => segname, - } - } - - /// Return the offset and size of the section in the file. - /// - /// Returns `None` for sections that have no data in the file. - fn file_range(&self, endian: Self::Endian) -> Option<(u64, u64)> { - match self.flags(endian) & macho::SECTION_TYPE { - macho::S_ZEROFILL | macho::S_GB_ZEROFILL | macho::S_THREAD_LOCAL_ZEROFILL => None, - _ => Some((self.offset(endian).into(), self.size(endian).into())), - } - } - - /// Return the section data. - /// - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values. - fn data<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> result::Result<&'data [u8], ()> { - if let Some((offset, size)) = self.file_range(endian) { - data.read_bytes_at(offset, size) - } else { - Ok(&[]) - } - } - - /// Return the relocation array. - /// - /// Returns `Err` for invalid values. - fn relocations<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> Result<&'data [macho::Relocation]> { - data.read_slice_at(self.reloff(endian).into(), self.nreloc(endian) as usize) - .read_error("Invalid Mach-O relocations offset or number") - } -} - -impl Section for macho::Section32 { - type Word = u32; - type Endian = Endian; - - fn sectname(&self) -> &[u8; 16] { - &self.sectname - } - fn segname(&self) -> &[u8; 16] { - &self.segname - } - fn addr(&self, endian: Self::Endian) -> Self::Word { - self.addr.get(endian) - } - fn size(&self, endian: Self::Endian) -> Self::Word { - self.size.get(endian) - } - fn offset(&self, endian: Self::Endian) -> u32 { - self.offset.get(endian) - } - fn align(&self, endian: Self::Endian) -> u32 { - self.align.get(endian) - } - fn reloff(&self, endian: Self::Endian) -> u32 { - self.reloff.get(endian) - } - fn nreloc(&self, endian: Self::Endian) -> u32 { - self.nreloc.get(endian) - } - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} - -impl Section for macho::Section64 { - type Word = u64; - type Endian = Endian; - - fn sectname(&self) -> &[u8; 16] { - &self.sectname - } - fn segname(&self) -> &[u8; 16] { - &self.segname - } - fn addr(&self, endian: Self::Endian) -> Self::Word { - self.addr.get(endian) - } - fn size(&self, endian: Self::Endian) -> Self::Word { - self.size.get(endian) - } - fn offset(&self, endian: Self::Endian) -> u32 { - self.offset.get(endian) - } - fn align(&self, endian: Self::Endian) -> u32 { - self.align.get(endian) - } - fn reloff(&self, endian: Self::Endian) -> u32 { - self.reloff.get(endian) - } - fn nreloc(&self, endian: Self::Endian) -> u32 { - self.nreloc.get(endian) - } - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} diff --git a/vendor/object/src/read/macho/segment.rs b/vendor/object/src/read/macho/segment.rs deleted file mode 100644 index c889ad2..0000000 --- a/vendor/object/src/read/macho/segment.rs +++ /dev/null @@ -1,303 +0,0 @@ -use core::fmt::Debug; -use core::{result, slice, str}; - -use crate::endian::{self, Endianness}; -use crate::macho; -use crate::pod::Pod; -use crate::read::{self, ObjectSegment, ReadError, ReadRef, Result, SegmentFlags}; - -use super::{LoadCommandData, MachHeader, MachOFile, Section}; - -/// An iterator for the segments in a [`MachOFile32`](super::MachOFile32). -pub type MachOSegmentIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSegmentIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the segments in a [`MachOFile64`](super::MachOFile64). -pub type MachOSegmentIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSegmentIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the segments in a [`MachOFile`]. -#[derive(Debug)] -pub struct MachOSegmentIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, - pub(super) iter: slice::Iter<'file, MachOSegmentInternal<'data, Mach, R>>, -} - -impl<'data, 'file, Mach, R> Iterator for MachOSegmentIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = MachOSegment<'data, 'file, Mach, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|internal| MachOSegment { - file: self.file, - internal, - }) - } -} - -/// A segment in a [`MachOFile32`](super::MachOFile32). -pub type MachOSegment32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSegment<'data, 'file, macho::MachHeader32, R>; -/// A segment in a [`MachOFile64`](super::MachOFile64). -pub type MachOSegment64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSegment<'data, 'file, macho::MachHeader64, R>; - -/// A segment in a [`MachOFile`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -#[derive(Debug)] -pub struct MachOSegment<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - file: &'file MachOFile<'data, Mach, R>, - internal: &'file MachOSegmentInternal<'data, Mach, R>, -} - -impl<'data, 'file, Mach, R> MachOSegment<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - fn bytes(&self) -> Result<&'data [u8]> { - self.internal - .segment - .data(self.file.endian, self.file.data) - .read_error("Invalid Mach-O segment size or offset") - } -} - -impl<'data, 'file, Mach, R> read::private::Sealed for MachOSegment<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> ObjectSegment<'data> for MachOSegment<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - #[inline] - fn address(&self) -> u64 { - self.internal.segment.vmaddr(self.file.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - self.internal.segment.vmsize(self.file.endian).into() - } - - #[inline] - fn align(&self) -> u64 { - // Page size. - 0x1000 - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - self.internal.segment.file_range(self.file.endian) - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn name_bytes(&self) -> Result> { - Ok(Some(self.internal.segment.name())) - } - - #[inline] - fn name(&self) -> Result> { - Ok(Some( - str::from_utf8(self.internal.segment.name()) - .ok() - .read_error("Non UTF-8 Mach-O segment name")?, - )) - } - - #[inline] - fn flags(&self) -> SegmentFlags { - let flags = self.internal.segment.flags(self.file.endian); - let maxprot = self.internal.segment.maxprot(self.file.endian); - let initprot = self.internal.segment.initprot(self.file.endian); - SegmentFlags::MachO { - flags, - maxprot, - initprot, - } - } -} - -#[derive(Debug, Clone, Copy)] -pub(super) struct MachOSegmentInternal<'data, Mach: MachHeader, R: ReadRef<'data>> { - pub data: R, - pub segment: &'data Mach::Segment, -} - -/// A trait for generic access to [`macho::SegmentCommand32`] and [`macho::SegmentCommand64`]. -#[allow(missing_docs)] -pub trait Segment: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - type Section: Section; - - fn from_command(command: LoadCommandData<'_, Self::Endian>) -> Result>; - - fn cmd(&self, endian: Self::Endian) -> u32; - fn cmdsize(&self, endian: Self::Endian) -> u32; - fn segname(&self) -> &[u8; 16]; - fn vmaddr(&self, endian: Self::Endian) -> Self::Word; - fn vmsize(&self, endian: Self::Endian) -> Self::Word; - fn fileoff(&self, endian: Self::Endian) -> Self::Word; - fn filesize(&self, endian: Self::Endian) -> Self::Word; - fn maxprot(&self, endian: Self::Endian) -> u32; - fn initprot(&self, endian: Self::Endian) -> u32; - fn nsects(&self, endian: Self::Endian) -> u32; - fn flags(&self, endian: Self::Endian) -> u32; - - /// Return the `segname` bytes up until the null terminator. - fn name(&self) -> &[u8] { - let segname = &self.segname()[..]; - match memchr::memchr(b'\0', segname) { - Some(end) => &segname[..end], - None => segname, - } - } - - /// Return the offset and size of the segment in the file. - fn file_range(&self, endian: Self::Endian) -> (u64, u64) { - (self.fileoff(endian).into(), self.filesize(endian).into()) - } - - /// Get the segment data from the file data. - /// - /// Returns `Err` for invalid values. - fn data<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - data: R, - ) -> result::Result<&'data [u8], ()> { - let (offset, size) = self.file_range(endian); - data.read_bytes_at(offset, size) - } - - /// Get the array of sections from the data following the segment command. - /// - /// Returns `Err` for invalid values. - fn sections<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - section_data: R, - ) -> Result<&'data [Self::Section]> { - section_data - .read_slice_at(0, self.nsects(endian) as usize) - .read_error("Invalid Mach-O number of sections") - } -} - -impl Segment for macho::SegmentCommand32 { - type Word = u32; - type Endian = Endian; - type Section = macho::Section32; - - fn from_command(command: LoadCommandData<'_, Self::Endian>) -> Result> { - command.segment_32() - } - - fn cmd(&self, endian: Self::Endian) -> u32 { - self.cmd.get(endian) - } - fn cmdsize(&self, endian: Self::Endian) -> u32 { - self.cmdsize.get(endian) - } - fn segname(&self) -> &[u8; 16] { - &self.segname - } - fn vmaddr(&self, endian: Self::Endian) -> Self::Word { - self.vmaddr.get(endian) - } - fn vmsize(&self, endian: Self::Endian) -> Self::Word { - self.vmsize.get(endian) - } - fn fileoff(&self, endian: Self::Endian) -> Self::Word { - self.fileoff.get(endian) - } - fn filesize(&self, endian: Self::Endian) -> Self::Word { - self.filesize.get(endian) - } - fn maxprot(&self, endian: Self::Endian) -> u32 { - self.maxprot.get(endian) - } - fn initprot(&self, endian: Self::Endian) -> u32 { - self.initprot.get(endian) - } - fn nsects(&self, endian: Self::Endian) -> u32 { - self.nsects.get(endian) - } - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} - -impl Segment for macho::SegmentCommand64 { - type Word = u64; - type Endian = Endian; - type Section = macho::Section64; - - fn from_command(command: LoadCommandData<'_, Self::Endian>) -> Result> { - command.segment_64() - } - - fn cmd(&self, endian: Self::Endian) -> u32 { - self.cmd.get(endian) - } - fn cmdsize(&self, endian: Self::Endian) -> u32 { - self.cmdsize.get(endian) - } - fn segname(&self) -> &[u8; 16] { - &self.segname - } - fn vmaddr(&self, endian: Self::Endian) -> Self::Word { - self.vmaddr.get(endian) - } - fn vmsize(&self, endian: Self::Endian) -> Self::Word { - self.vmsize.get(endian) - } - fn fileoff(&self, endian: Self::Endian) -> Self::Word { - self.fileoff.get(endian) - } - fn filesize(&self, endian: Self::Endian) -> Self::Word { - self.filesize.get(endian) - } - fn maxprot(&self, endian: Self::Endian) -> u32 { - self.maxprot.get(endian) - } - fn initprot(&self, endian: Self::Endian) -> u32 { - self.initprot.get(endian) - } - fn nsects(&self, endian: Self::Endian) -> u32 { - self.nsects.get(endian) - } - fn flags(&self, endian: Self::Endian) -> u32 { - self.flags.get(endian) - } -} diff --git a/vendor/object/src/read/macho/symbol.rs b/vendor/object/src/read/macho/symbol.rs deleted file mode 100644 index 434361f..0000000 --- a/vendor/object/src/read/macho/symbol.rs +++ /dev/null @@ -1,492 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; -use core::{fmt, slice, str}; - -use crate::endian::{self, Endianness}; -use crate::macho; -use crate::pod::Pod; -use crate::read::util::StringTable; -use crate::read::{ - self, ObjectMap, ObjectMapEntry, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, - SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, - SymbolScope, SymbolSection, -}; - -use super::{MachHeader, MachOFile}; - -/// A table of symbol entries in a Mach-O file. -/// -/// Also includes the string table used for the symbol names. -/// -/// Returned by [`macho::SymtabCommand::symbols`]. -#[derive(Debug, Clone, Copy)] -pub struct SymbolTable<'data, Mach: MachHeader, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - symbols: &'data [Mach::Nlist], - strings: StringTable<'data, R>, -} - -impl<'data, Mach: MachHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Mach, R> { - fn default() -> Self { - SymbolTable { - symbols: &[], - strings: Default::default(), - } - } -} - -impl<'data, Mach: MachHeader, R: ReadRef<'data>> SymbolTable<'data, Mach, R> { - #[inline] - pub(super) fn new(symbols: &'data [Mach::Nlist], strings: StringTable<'data, R>) -> Self { - SymbolTable { symbols, strings } - } - - /// Return the string table used for the symbol names. - #[inline] - pub fn strings(&self) -> StringTable<'data, R> { - self.strings - } - - /// Iterate over the symbols. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, Mach::Nlist> { - self.symbols.iter() - } - - /// Return true if the symbol table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// The number of symbols. - #[inline] - pub fn len(&self) -> usize { - self.symbols.len() - } - - /// Return the symbol at the given index. - pub fn symbol(&self, index: usize) -> Result<&'data Mach::Nlist> { - self.symbols - .get(index) - .read_error("Invalid Mach-O symbol index") - } - - /// Construct a map from addresses to a user-defined map entry. - pub fn map Option>( - &self, - f: F, - ) -> SymbolMap { - let mut symbols = Vec::new(); - for nlist in self.symbols { - if !nlist.is_definition() { - continue; - } - if let Some(entry) = f(nlist) { - symbols.push(entry); - } - } - SymbolMap::new(symbols) - } - - /// Construct a map from addresses to symbol names and object file names. - pub fn object_map(&self, endian: Mach::Endian) -> ObjectMap<'data> { - let mut symbols = Vec::new(); - let mut objects = Vec::new(); - let mut object = None; - let mut current_function = None; - // Each module starts with one or two N_SO symbols (path, or directory + filename) - // and one N_OSO symbol. The module is terminated by an empty N_SO symbol. - for nlist in self.symbols { - let n_type = nlist.n_type(); - if n_type & macho::N_STAB == 0 { - continue; - } - // TODO: includes variables too (N_GSYM, N_STSYM). These may need to get their - // address from regular symbols though. - match n_type { - macho::N_SO => { - object = None; - } - macho::N_OSO => { - object = None; - if let Ok(name) = nlist.name(endian, self.strings) { - if !name.is_empty() { - object = Some(objects.len()); - objects.push(name); - } - } - } - macho::N_FUN => { - if let Ok(name) = nlist.name(endian, self.strings) { - if !name.is_empty() { - current_function = Some((name, nlist.n_value(endian).into())) - } else if let Some((name, address)) = current_function.take() { - if let Some(object) = object { - symbols.push(ObjectMapEntry { - address, - size: nlist.n_value(endian).into(), - name, - object, - }); - } - } - } - } - _ => {} - } - } - ObjectMap { - symbols: SymbolMap::new(symbols), - objects, - } - } -} - -/// A symbol table in a [`MachOFile32`](super::MachOFile32). -pub type MachOSymbolTable32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbolTable<'data, 'file, macho::MachHeader32, R>; -/// A symbol table in a [`MachOFile64`](super::MachOFile64). -pub type MachOSymbolTable64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbolTable<'data, 'file, macho::MachHeader64, R>; - -/// A symbol table in a [`MachOFile`]. -#[derive(Debug, Clone, Copy)] -pub struct MachOSymbolTable<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, -} - -impl<'data, 'file, Mach, R> read::private::Sealed for MachOSymbolTable<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> ObjectSymbolTable<'data> for MachOSymbolTable<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Symbol = MachOSymbol<'data, 'file, Mach, R>; - type SymbolIterator = MachOSymbolIterator<'data, 'file, Mach, R>; - - fn symbols(&self) -> Self::SymbolIterator { - MachOSymbolIterator { - file: self.file, - index: 0, - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> Result { - let nlist = self.file.symbols.symbol(index.0)?; - MachOSymbol::new(self.file, index, nlist).read_error("Unsupported Mach-O symbol index") - } -} - -/// An iterator for the symbols in a [`MachOFile32`](super::MachOFile32). -pub type MachOSymbolIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbolIterator<'data, 'file, macho::MachHeader32, R>; -/// An iterator for the symbols in a [`MachOFile64`](super::MachOFile64). -pub type MachOSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbolIterator<'data, 'file, macho::MachHeader64, R>; - -/// An iterator for the symbols in a [`MachOFile`]. -pub struct MachOSymbolIterator<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file MachOFile<'data, Mach, R>, - pub(super) index: usize, -} - -impl<'data, 'file, Mach, R> fmt::Debug for MachOSymbolIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MachOSymbolIterator").finish() - } -} - -impl<'data, 'file, Mach, R> Iterator for MachOSymbolIterator<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - type Item = MachOSymbol<'data, 'file, Mach, R>; - - fn next(&mut self) -> Option { - loop { - let index = self.index; - let nlist = self.file.symbols.symbols.get(index)?; - self.index += 1; - if let Some(symbol) = MachOSymbol::new(self.file, SymbolIndex(index), nlist) { - return Some(symbol); - } - } - } -} - -/// A symbol in a [`MachOFile32`](super::MachOFile32). -pub type MachOSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbol<'data, 'file, macho::MachHeader32, R>; -/// A symbol in a [`MachOFile64`](super::MachOFile64). -pub type MachOSymbol64<'data, 'file, Endian = Endianness, R = &'data [u8]> = - MachOSymbol<'data, 'file, macho::MachHeader64, R>; - -/// A symbol in a [`MachOFile`]. -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Debug, Clone, Copy)] -pub struct MachOSymbol<'data, 'file, Mach, R = &'data [u8]> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - file: &'file MachOFile<'data, Mach, R>, - index: SymbolIndex, - nlist: &'data Mach::Nlist, -} - -impl<'data, 'file, Mach, R> MachOSymbol<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - pub(super) fn new( - file: &'file MachOFile<'data, Mach, R>, - index: SymbolIndex, - nlist: &'data Mach::Nlist, - ) -> Option { - if nlist.n_type() & macho::N_STAB != 0 { - return None; - } - Some(MachOSymbol { file, index, nlist }) - } -} - -impl<'data, 'file, Mach, R> read::private::Sealed for MachOSymbol<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Mach, R> ObjectSymbol<'data> for MachOSymbol<'data, 'file, Mach, R> -where - Mach: MachHeader, - R: ReadRef<'data>, -{ - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - fn name_bytes(&self) -> Result<&'data [u8]> { - self.nlist.name(self.file.endian, self.file.symbols.strings) - } - - fn name(&self) -> Result<&'data str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 Mach-O symbol name") - } - - #[inline] - fn address(&self) -> u64 { - self.nlist.n_value(self.file.endian).into() - } - - #[inline] - fn size(&self) -> u64 { - 0 - } - - fn kind(&self) -> SymbolKind { - self.section() - .index() - .and_then(|index| self.file.section_internal(index).ok()) - .map(|section| match section.kind { - SectionKind::Text => SymbolKind::Text, - SectionKind::Data - | SectionKind::ReadOnlyData - | SectionKind::ReadOnlyString - | SectionKind::UninitializedData - | SectionKind::Common => SymbolKind::Data, - SectionKind::Tls | SectionKind::UninitializedTls | SectionKind::TlsVariables => { - SymbolKind::Tls - } - _ => SymbolKind::Unknown, - }) - .unwrap_or(SymbolKind::Unknown) - } - - fn section(&self) -> SymbolSection { - match self.nlist.n_type() & macho::N_TYPE { - macho::N_UNDF => SymbolSection::Undefined, - macho::N_ABS => SymbolSection::Absolute, - macho::N_SECT => { - let n_sect = self.nlist.n_sect(); - if n_sect != 0 { - SymbolSection::Section(SectionIndex(n_sect as usize)) - } else { - SymbolSection::Unknown - } - } - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.nlist.n_type() & macho::N_TYPE == macho::N_UNDF - } - - #[inline] - fn is_definition(&self) -> bool { - self.nlist.is_definition() - } - - #[inline] - fn is_common(&self) -> bool { - // Mach-O common symbols are based on section, not symbol - false - } - - #[inline] - fn is_weak(&self) -> bool { - self.nlist.n_desc(self.file.endian) & (macho::N_WEAK_REF | macho::N_WEAK_DEF) != 0 - } - - fn scope(&self) -> SymbolScope { - let n_type = self.nlist.n_type(); - if n_type & macho::N_TYPE == macho::N_UNDF { - SymbolScope::Unknown - } else if n_type & macho::N_EXT == 0 { - SymbolScope::Compilation - } else if n_type & macho::N_PEXT != 0 { - SymbolScope::Linkage - } else { - SymbolScope::Dynamic - } - } - - #[inline] - fn is_global(&self) -> bool { - self.scope() != SymbolScope::Compilation - } - - #[inline] - fn is_local(&self) -> bool { - self.scope() == SymbolScope::Compilation - } - - #[inline] - fn flags(&self) -> SymbolFlags { - let n_desc = self.nlist.n_desc(self.file.endian); - SymbolFlags::MachO { n_desc } - } -} - -/// A trait for generic access to [`macho::Nlist32`] and [`macho::Nlist64`]. -#[allow(missing_docs)] -pub trait Nlist: Debug + Pod { - type Word: Into; - type Endian: endian::Endian; - - fn n_strx(&self, endian: Self::Endian) -> u32; - fn n_type(&self) -> u8; - fn n_sect(&self) -> u8; - fn n_desc(&self, endian: Self::Endian) -> u16; - fn n_value(&self, endian: Self::Endian) -> Self::Word; - - fn name<'data, R: ReadRef<'data>>( - &self, - endian: Self::Endian, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - strings - .get(self.n_strx(endian)) - .read_error("Invalid Mach-O symbol name offset") - } - - /// Return true if this is a STAB symbol. - /// - /// This determines the meaning of the `n_type` field. - fn is_stab(&self) -> bool { - self.n_type() & macho::N_STAB != 0 - } - - /// Return true if this is an undefined symbol. - fn is_undefined(&self) -> bool { - let n_type = self.n_type(); - n_type & macho::N_STAB == 0 && n_type & macho::N_TYPE == macho::N_UNDF - } - - /// Return true if the symbol is a definition of a function or data object. - fn is_definition(&self) -> bool { - let n_type = self.n_type(); - n_type & macho::N_STAB == 0 && n_type & macho::N_TYPE == macho::N_SECT - } - - /// Return the library ordinal. - /// - /// This is either a 1-based index into the dylib load commands, - /// or a special ordinal. - #[inline] - fn library_ordinal(&self, endian: Self::Endian) -> u8 { - (self.n_desc(endian) >> 8) as u8 - } -} - -impl Nlist for macho::Nlist32 { - type Word = u32; - type Endian = Endian; - - fn n_strx(&self, endian: Self::Endian) -> u32 { - self.n_strx.get(endian) - } - fn n_type(&self) -> u8 { - self.n_type - } - fn n_sect(&self) -> u8 { - self.n_sect - } - fn n_desc(&self, endian: Self::Endian) -> u16 { - self.n_desc.get(endian) - } - fn n_value(&self, endian: Self::Endian) -> Self::Word { - self.n_value.get(endian) - } -} - -impl Nlist for macho::Nlist64 { - type Word = u64; - type Endian = Endian; - - fn n_strx(&self, endian: Self::Endian) -> u32 { - self.n_strx.get(endian) - } - fn n_type(&self) -> u8 { - self.n_type - } - fn n_sect(&self) -> u8 { - self.n_sect - } - fn n_desc(&self, endian: Self::Endian) -> u16 { - self.n_desc.get(endian) - } - fn n_value(&self, endian: Self::Endian) -> Self::Word { - self.n_value.get(endian) - } -} diff --git a/vendor/object/src/read/mod.rs b/vendor/object/src/read/mod.rs deleted file mode 100644 index c13e309..0000000 --- a/vendor/object/src/read/mod.rs +++ /dev/null @@ -1,860 +0,0 @@ -//! Interface for reading object files. -//! -//! ## Unified read API -//! -//! The [`Object`] trait provides a unified read API for accessing common features of -//! object files, such as sections and symbols. There is an implementation of this -//! trait for [`File`], which allows reading any file format, as well as implementations -//! for each file format: -//! [`ElfFile`](elf::ElfFile), [`MachOFile`](macho::MachOFile), [`CoffFile`](coff::CoffFile), -//! [`PeFile`](pe::PeFile), [`WasmFile`](wasm::WasmFile), [`XcoffFile`](xcoff::XcoffFile). -//! -//! ## Low level read API -//! -//! The submodules for each file format define helpers that operate on the raw structs. -//! These can be used instead of the unified API, or in conjunction with it to access -//! details that are not available via the unified API. -//! -//! See the [submodules](#modules) for examples of the low level read API. -//! -//! ## Naming Convention -//! -//! Types that form part of the unified API for a file format are prefixed with the -//! name of the file format. -//! -//! ## Example for unified read API -//! ```no_run -//! use object::{Object, ObjectSection}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each section. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let file = object::File::parse(&*data)?; -//! for section in file.sections() { -//! println!("{}", section.name()?); -//! } -//! # } -//! Ok(()) -//! } -//! ``` - -use alloc::borrow::Cow; -use alloc::vec::Vec; -use core::{fmt, result}; - -use crate::common::*; - -mod read_ref; -pub use read_ref::*; - -#[cfg(feature = "std")] -mod read_cache; -#[cfg(feature = "std")] -pub use read_cache::*; - -mod util; -pub use util::*; - -#[cfg(any( - feature = "coff", - feature = "elf", - feature = "macho", - feature = "pe", - feature = "wasm", - feature = "xcoff" -))] -mod any; -#[cfg(any( - feature = "coff", - feature = "elf", - feature = "macho", - feature = "pe", - feature = "wasm", - feature = "xcoff" -))] -pub use any::*; - -#[cfg(feature = "archive")] -pub mod archive; - -#[cfg(feature = "coff")] -pub mod coff; - -#[cfg(feature = "elf")] -pub mod elf; - -#[cfg(feature = "macho")] -pub mod macho; - -#[cfg(feature = "pe")] -pub mod pe; - -#[cfg(feature = "wasm")] -pub mod wasm; - -#[cfg(feature = "xcoff")] -pub mod xcoff; - -mod traits; -pub use traits::*; - -mod private { - pub trait Sealed {} -} - -/// The error type used within the read module. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Error(&'static str); - -impl fmt::Display for Error { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.0) - } -} - -#[cfg(feature = "std")] -impl std::error::Error for Error {} - -/// The result type used within the read module. -pub type Result = result::Result; - -trait ReadError { - fn read_error(self, error: &'static str) -> Result; -} - -impl ReadError for result::Result { - fn read_error(self, error: &'static str) -> Result { - self.map_err(|()| Error(error)) - } -} - -impl ReadError for result::Result { - fn read_error(self, error: &'static str) -> Result { - self.map_err(|_| Error(error)) - } -} - -impl ReadError for Option { - fn read_error(self, error: &'static str) -> Result { - self.ok_or(Error(error)) - } -} - -/// The native executable file for the target platform. -#[cfg(all( - unix, - not(target_os = "macos"), - target_pointer_width = "32", - feature = "elf" -))] -pub type NativeFile<'data, R = &'data [u8]> = elf::ElfFile32<'data, crate::Endianness, R>; - -/// The native executable file for the target platform. -#[cfg(all( - unix, - not(target_os = "macos"), - target_pointer_width = "64", - feature = "elf" -))] -pub type NativeFile<'data, R = &'data [u8]> = elf::ElfFile64<'data, crate::Endianness, R>; - -/// The native executable file for the target platform. -#[cfg(all(target_os = "macos", target_pointer_width = "32", feature = "macho"))] -pub type NativeFile<'data, R = &'data [u8]> = macho::MachOFile32<'data, crate::Endianness, R>; - -/// The native executable file for the target platform. -#[cfg(all(target_os = "macos", target_pointer_width = "64", feature = "macho"))] -pub type NativeFile<'data, R = &'data [u8]> = macho::MachOFile64<'data, crate::Endianness, R>; - -/// The native executable file for the target platform. -#[cfg(all(target_os = "windows", target_pointer_width = "32", feature = "pe"))] -pub type NativeFile<'data, R = &'data [u8]> = pe::PeFile32<'data, R>; - -/// The native executable file for the target platform. -#[cfg(all(target_os = "windows", target_pointer_width = "64", feature = "pe"))] -pub type NativeFile<'data, R = &'data [u8]> = pe::PeFile64<'data, R>; - -/// The native executable file for the target platform. -#[cfg(all(feature = "wasm", target_arch = "wasm32", feature = "wasm"))] -pub type NativeFile<'data, R = &'data [u8]> = wasm::WasmFile<'data, R>; - -/// A file format kind. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum FileKind { - /// A Unix archive. - /// - /// See [`archive::ArchiveFile`]. - #[cfg(feature = "archive")] - Archive, - /// A COFF object file. - /// - /// See [`coff::CoffFile`]. - #[cfg(feature = "coff")] - Coff, - /// A COFF bigobj object file. - /// - /// This supports a larger number of sections. - /// - /// See [`coff::CoffBigFile`]. - #[cfg(feature = "coff")] - CoffBig, - /// A Windows short import file. - /// - /// See [`coff::ImportFile`]. - #[cfg(feature = "coff")] - CoffImport, - /// A dyld cache file containing Mach-O images. - /// - /// See [`macho::DyldCache`] - #[cfg(feature = "macho")] - DyldCache, - /// A 32-bit ELF file. - /// - /// See [`elf::ElfFile32`]. - #[cfg(feature = "elf")] - Elf32, - /// A 64-bit ELF file. - /// - /// See [`elf::ElfFile64`]. - #[cfg(feature = "elf")] - Elf64, - /// A 32-bit Mach-O file. - /// - /// See [`macho::MachOFile32`]. - #[cfg(feature = "macho")] - MachO32, - /// A 64-bit Mach-O file. - /// - /// See [`macho::MachOFile64`]. - #[cfg(feature = "macho")] - MachO64, - /// A 32-bit Mach-O fat binary. - /// - /// See [`macho::FatHeader::parse_arch32`]. - #[cfg(feature = "macho")] - MachOFat32, - /// A 64-bit Mach-O fat binary. - /// - /// See [`macho::FatHeader::parse_arch64`]. - #[cfg(feature = "macho")] - MachOFat64, - /// A 32-bit PE file. - /// - /// See [`pe::PeFile32`]. - #[cfg(feature = "pe")] - Pe32, - /// A 64-bit PE file. - /// - /// See [`pe::PeFile64`]. - #[cfg(feature = "pe")] - Pe64, - /// A Wasm file. - /// - /// See [`wasm::WasmFile`]. - #[cfg(feature = "wasm")] - Wasm, - /// A 32-bit XCOFF file. - /// - /// See [`xcoff::XcoffFile32`]. - #[cfg(feature = "xcoff")] - Xcoff32, - /// A 64-bit XCOFF file. - /// - /// See [`xcoff::XcoffFile64`]. - #[cfg(feature = "xcoff")] - Xcoff64, -} - -impl FileKind { - /// Determine a file kind by parsing the start of the file. - pub fn parse<'data, R: ReadRef<'data>>(data: R) -> Result { - Self::parse_at(data, 0) - } - - /// Determine a file kind by parsing at the given offset. - pub fn parse_at<'data, R: ReadRef<'data>>(data: R, offset: u64) -> Result { - let magic = data - .read_bytes_at(offset, 16) - .read_error("Could not read file magic")?; - if magic.len() < 16 { - return Err(Error("File too short")); - } - - let kind = match [magic[0], magic[1], magic[2], magic[3], magic[4], magic[5], magic[6], magic[7]] { - #[cfg(feature = "archive")] - [b'!', b'<', b'a', b'r', b'c', b'h', b'>', b'\n'] => FileKind::Archive, - #[cfg(feature = "macho")] - [b'd', b'y', b'l', b'd', b'_', b'v', b'1', b' '] => FileKind::DyldCache, - #[cfg(feature = "elf")] - [0x7f, b'E', b'L', b'F', 1, ..] => FileKind::Elf32, - #[cfg(feature = "elf")] - [0x7f, b'E', b'L', b'F', 2, ..] => FileKind::Elf64, - #[cfg(feature = "macho")] - [0xfe, 0xed, 0xfa, 0xce, ..] - | [0xce, 0xfa, 0xed, 0xfe, ..] => FileKind::MachO32, - #[cfg(feature = "macho")] - | [0xfe, 0xed, 0xfa, 0xcf, ..] - | [0xcf, 0xfa, 0xed, 0xfe, ..] => FileKind::MachO64, - #[cfg(feature = "macho")] - [0xca, 0xfe, 0xba, 0xbe, ..] => FileKind::MachOFat32, - #[cfg(feature = "macho")] - [0xca, 0xfe, 0xba, 0xbf, ..] => FileKind::MachOFat64, - #[cfg(feature = "wasm")] - [0x00, b'a', b's', b'm', ..] => FileKind::Wasm, - #[cfg(feature = "pe")] - [b'M', b'Z', ..] if offset == 0 => { - // offset == 0 restriction is because optional_header_magic only looks at offset 0 - match pe::optional_header_magic(data) { - Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => { - FileKind::Pe32 - } - Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => { - FileKind::Pe64 - } - _ => return Err(Error("Unknown MS-DOS file")), - } - } - // TODO: more COFF machines - #[cfg(feature = "coff")] - // COFF arm - [0xc4, 0x01, ..] - // COFF arm64 - | [0x64, 0xaa, ..] - // COFF arm64ec - | [0x41, 0xa6, ..] - // COFF x86 - | [0x4c, 0x01, ..] - // COFF x86-64 - | [0x64, 0x86, ..] => FileKind::Coff, - #[cfg(feature = "coff")] - [0x00, 0x00, 0xff, 0xff, 0x00, 0x00, ..] => FileKind::CoffImport, - #[cfg(feature = "coff")] - [0x00, 0x00, 0xff, 0xff, 0x02, 0x00, ..] if offset == 0 => { - // offset == 0 restriction is because anon_object_class_id only looks at offset 0 - match coff::anon_object_class_id(data) { - Ok(crate::pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID) => FileKind::CoffBig, - _ => return Err(Error("Unknown anon object file")), - } - } - #[cfg(feature = "xcoff")] - [0x01, 0xdf, ..] => FileKind::Xcoff32, - #[cfg(feature = "xcoff")] - [0x01, 0xf7, ..] => FileKind::Xcoff64, - _ => return Err(Error("Unknown file magic")), - }; - Ok(kind) - } -} - -/// An object kind. -/// -/// Returned by [`Object::kind`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ObjectKind { - /// The object kind is unknown. - Unknown, - /// Relocatable object. - Relocatable, - /// Executable. - Executable, - /// Dynamic shared object. - Dynamic, - /// Core. - Core, -} - -/// The index used to identify a section in a file. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct SectionIndex(pub usize); - -/// The index used to identify a symbol in a symbol table. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct SymbolIndex(pub usize); - -/// The section where an [`ObjectSymbol`] is defined. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SymbolSection { - /// The section is unknown. - Unknown, - /// The section is not applicable for this symbol (such as file symbols). - None, - /// The symbol is undefined. - Undefined, - /// The symbol has an absolute value. - Absolute, - /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions. - Common, - /// The symbol is defined in the given section. - Section(SectionIndex), -} - -impl SymbolSection { - /// Returns the section index for the section where the symbol is defined. - /// - /// May return `None` if the symbol is not defined in a section. - #[inline] - pub fn index(self) -> Option { - if let SymbolSection::Section(index) = self { - Some(index) - } else { - None - } - } -} - -/// An entry in a [`SymbolMap`]. -pub trait SymbolMapEntry { - /// The symbol address. - fn address(&self) -> u64; -} - -/// A map from addresses to symbol information. -/// -/// The symbol information depends on the chosen entry type, such as [`SymbolMapName`]. -/// -/// Returned by [`Object::symbol_map`]. -#[derive(Debug, Default, Clone)] -pub struct SymbolMap { - symbols: Vec, -} - -impl SymbolMap { - /// Construct a new symbol map. - /// - /// This function will sort the symbols by address. - pub fn new(mut symbols: Vec) -> Self { - symbols.sort_by_key(|s| s.address()); - SymbolMap { symbols } - } - - /// Get the symbol before the given address. - pub fn get(&self, address: u64) -> Option<&T> { - let index = match self - .symbols - .binary_search_by_key(&address, |symbol| symbol.address()) - { - Ok(index) => index, - Err(index) => index.checked_sub(1)?, - }; - self.symbols.get(index) - } - - /// Get all symbols in the map. - #[inline] - pub fn symbols(&self) -> &[T] { - &self.symbols - } -} - -/// The type used for entries in a [`SymbolMap`] that maps from addresses to names. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct SymbolMapName<'data> { - address: u64, - name: &'data str, -} - -impl<'data> SymbolMapName<'data> { - /// Construct a `SymbolMapName`. - pub fn new(address: u64, name: &'data str) -> Self { - SymbolMapName { address, name } - } - - /// The symbol address. - #[inline] - pub fn address(&self) -> u64 { - self.address - } - - /// The symbol name. - #[inline] - pub fn name(&self) -> &'data str { - self.name - } -} - -impl<'data> SymbolMapEntry for SymbolMapName<'data> { - #[inline] - fn address(&self) -> u64 { - self.address - } -} - -/// A map from addresses to symbol names and object files. -/// -/// This is derived from STAB entries in Mach-O files. -/// -/// Returned by [`Object::object_map`]. -#[derive(Debug, Default, Clone)] -pub struct ObjectMap<'data> { - symbols: SymbolMap>, - objects: Vec<&'data [u8]>, -} - -impl<'data> ObjectMap<'data> { - /// Get the entry containing the given address. - pub fn get(&self, address: u64) -> Option<&ObjectMapEntry<'data>> { - self.symbols - .get(address) - .filter(|entry| entry.size == 0 || address.wrapping_sub(entry.address) < entry.size) - } - - /// Get all symbols in the map. - #[inline] - pub fn symbols(&self) -> &[ObjectMapEntry<'data>] { - self.symbols.symbols() - } - - /// Get all objects in the map. - #[inline] - pub fn objects(&self) -> &[&'data [u8]] { - &self.objects - } -} - -/// An [`ObjectMap`] entry. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ObjectMapEntry<'data> { - address: u64, - size: u64, - name: &'data [u8], - object: usize, -} - -impl<'data> ObjectMapEntry<'data> { - /// Get the symbol address. - #[inline] - pub fn address(&self) -> u64 { - self.address - } - - /// Get the symbol size. - /// - /// This may be 0 if the size is unknown. - #[inline] - pub fn size(&self) -> u64 { - self.size - } - - /// Get the symbol name. - #[inline] - pub fn name(&self) -> &'data [u8] { - self.name - } - - /// Get the index of the object file name. - #[inline] - pub fn object_index(&self) -> usize { - self.object - } - - /// Get the object file name. - #[inline] - pub fn object(&self, map: &ObjectMap<'data>) -> &'data [u8] { - map.objects[self.object] - } -} - -impl<'data> SymbolMapEntry for ObjectMapEntry<'data> { - #[inline] - fn address(&self) -> u64 { - self.address - } -} - -/// An imported symbol. -/// -/// Returned by [`Object::imports`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Import<'data> { - library: ByteString<'data>, - // TODO: or ordinal - name: ByteString<'data>, -} - -impl<'data> Import<'data> { - /// The symbol name. - #[inline] - pub fn name(&self) -> &'data [u8] { - self.name.0 - } - - /// The name of the library to import the symbol from. - #[inline] - pub fn library(&self) -> &'data [u8] { - self.library.0 - } -} - -/// An exported symbol. -/// -/// Returned by [`Object::exports`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Export<'data> { - // TODO: and ordinal? - name: ByteString<'data>, - address: u64, -} - -impl<'data> Export<'data> { - /// The symbol name. - #[inline] - pub fn name(&self) -> &'data [u8] { - self.name.0 - } - - /// The virtual address of the symbol. - #[inline] - pub fn address(&self) -> u64 { - self.address - } -} - -/// PDB information from the debug directory in a PE file. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct CodeView<'data> { - guid: [u8; 16], - path: ByteString<'data>, - age: u32, -} - -impl<'data> CodeView<'data> { - /// The path to the PDB as stored in CodeView. - #[inline] - pub fn path(&self) -> &'data [u8] { - self.path.0 - } - - /// The age of the PDB. - #[inline] - pub fn age(&self) -> u32 { - self.age - } - - /// The GUID of the PDB. - #[inline] - pub fn guid(&self) -> [u8; 16] { - self.guid - } -} - -/// The target referenced by a [`Relocation`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum RelocationTarget { - /// The target is a symbol. - Symbol(SymbolIndex), - /// The target is a section. - Section(SectionIndex), - /// The offset is an absolute address. - Absolute, -} - -/// A relocation entry. -/// -/// Returned by [`Object::dynamic_relocations`] or [`ObjectSection::relocations`]. -#[derive(Debug)] -pub struct Relocation { - kind: RelocationKind, - encoding: RelocationEncoding, - size: u8, - target: RelocationTarget, - addend: i64, - implicit_addend: bool, -} - -impl Relocation { - /// The operation used to calculate the result of the relocation. - #[inline] - pub fn kind(&self) -> RelocationKind { - self.kind - } - - /// Information about how the result of the relocation operation is encoded in the place. - #[inline] - pub fn encoding(&self) -> RelocationEncoding { - self.encoding - } - - /// The size in bits of the place of the relocation. - /// - /// If 0, then the size is determined by the relocation kind. - #[inline] - pub fn size(&self) -> u8 { - self.size - } - - /// The target of the relocation. - #[inline] - pub fn target(&self) -> RelocationTarget { - self.target - } - - /// The addend to use in the relocation calculation. - #[inline] - pub fn addend(&self) -> i64 { - self.addend - } - - /// Set the addend to use in the relocation calculation. - #[inline] - pub fn set_addend(&mut self, addend: i64) { - self.addend = addend - } - - /// Returns true if there is an implicit addend stored in the data at the offset - /// to be relocated. - #[inline] - pub fn has_implicit_addend(&self) -> bool { - self.implicit_addend - } -} - -/// A data compression format. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum CompressionFormat { - /// The data is uncompressed. - None, - /// The data is compressed, but the compression format is unknown. - Unknown, - /// ZLIB/DEFLATE. - /// - /// Used for ELF compression and GNU compressed debug information. - Zlib, - /// Zstandard. - /// - /// Used for ELF compression. - Zstandard, -} - -/// A range in a file that may be compressed. -/// -/// Returned by [`ObjectSection::compressed_file_range`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct CompressedFileRange { - /// The data compression format. - pub format: CompressionFormat, - /// The file offset of the compressed data. - pub offset: u64, - /// The compressed data size. - pub compressed_size: u64, - /// The uncompressed data size. - pub uncompressed_size: u64, -} - -impl CompressedFileRange { - /// Data that is uncompressed. - #[inline] - pub fn none(range: Option<(u64, u64)>) -> Self { - if let Some((offset, size)) = range { - CompressedFileRange { - format: CompressionFormat::None, - offset, - compressed_size: size, - uncompressed_size: size, - } - } else { - CompressedFileRange { - format: CompressionFormat::None, - offset: 0, - compressed_size: 0, - uncompressed_size: 0, - } - } - } - - /// Convert to [`CompressedData`] by reading from the file. - pub fn data<'data, R: ReadRef<'data>>(self, file: R) -> Result> { - let data = file - .read_bytes_at(self.offset, self.compressed_size) - .read_error("Invalid compressed data size or offset")?; - Ok(CompressedData { - format: self.format, - data, - uncompressed_size: self.uncompressed_size, - }) - } -} - -/// Data that may be compressed. -/// -/// Returned by [`ObjectSection::compressed_data`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct CompressedData<'data> { - /// The data compression format. - pub format: CompressionFormat, - /// The compressed data. - pub data: &'data [u8], - /// The uncompressed data size. - pub uncompressed_size: u64, -} - -impl<'data> CompressedData<'data> { - /// Data that is uncompressed. - #[inline] - pub fn none(data: &'data [u8]) -> Self { - CompressedData { - format: CompressionFormat::None, - data, - uncompressed_size: data.len() as u64, - } - } - - /// Return the uncompressed data. - /// - /// Returns an error for invalid data or unsupported compression. - /// This includes if the data is compressed but the `compression` feature - /// for this crate is disabled. - pub fn decompress(self) -> Result> { - match self.format { - CompressionFormat::None => Ok(Cow::Borrowed(self.data)), - #[cfg(feature = "compression")] - CompressionFormat::Zlib => { - use core::convert::TryInto; - let size = self - .uncompressed_size - .try_into() - .ok() - .read_error("Uncompressed data size is too large.")?; - let mut decompressed = Vec::with_capacity(size); - let mut decompress = flate2::Decompress::new(true); - decompress - .decompress_vec( - self.data, - &mut decompressed, - flate2::FlushDecompress::Finish, - ) - .ok() - .read_error("Invalid zlib compressed data")?; - Ok(Cow::Owned(decompressed)) - } - #[cfg(feature = "compression")] - CompressionFormat::Zstandard => { - use core::convert::TryInto; - use std::io::Read; - let size = self - .uncompressed_size - .try_into() - .ok() - .read_error("Uncompressed data size is too large.")?; - let mut decompressed = Vec::with_capacity(size); - let mut decoder = ruzstd::StreamingDecoder::new(self.data) - .ok() - .read_error("Invalid zstd compressed data")?; - decoder - .read_to_end(&mut decompressed) - .ok() - .read_error("Invalid zstd compressed data")?; - Ok(Cow::Owned(decompressed)) - } - _ => Err(Error("Unsupported compressed data.")), - } - } -} diff --git a/vendor/object/src/read/pe/data_directory.rs b/vendor/object/src/read/pe/data_directory.rs deleted file mode 100644 index a17179f..0000000 --- a/vendor/object/src/read/pe/data_directory.rs +++ /dev/null @@ -1,213 +0,0 @@ -use core::slice; - -use crate::read::{Error, ReadError, ReadRef, Result}; -use crate::{pe, LittleEndian as LE}; - -use super::{ - DelayLoadImportTable, ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory, - SectionTable, -}; - -/// The table of data directories in a PE file. -/// -/// Returned by [`ImageNtHeaders::parse`](super::ImageNtHeaders::parse). -#[derive(Debug, Clone, Copy)] -pub struct DataDirectories<'data> { - entries: &'data [pe::ImageDataDirectory], -} - -impl<'data> DataDirectories<'data> { - /// Parse the data directory table. - /// - /// `data` must be the remaining optional data following the - /// [optional header](pe::ImageOptionalHeader64). `number` must be from the - /// [`number_of_rva_and_sizes`](pe::ImageOptionalHeader64::number_of_rva_and_sizes) - /// field of the optional header. - pub fn parse(data: &'data [u8], number: u32) -> Result { - let entries = data - .read_slice_at(0, number as usize) - .read_error("Invalid PE number of RVA and sizes")?; - Ok(DataDirectories { entries }) - } - - /// The number of data directories. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.entries.len() - } - - /// Iterator over the data directories. - pub fn iter(&self) -> slice::Iter<'data, pe::ImageDataDirectory> { - self.entries.iter() - } - - /// Iterator which gives the directories as well as their index (one of the IMAGE_DIRECTORY_ENTRY_* constants). - pub fn enumerate(&self) -> core::iter::Enumerate> { - self.entries.iter().enumerate() - } - - /// Returns the data directory at the given index. - /// - /// Index should be one of the `IMAGE_DIRECTORY_ENTRY_*` constants. - /// - /// Returns `None` if the index is larger than the table size, - /// or if the entry at the index has a zero virtual address. - pub fn get(&self, index: usize) -> Option<&'data pe::ImageDataDirectory> { - self.entries - .get(index) - .filter(|d| d.virtual_address.get(LE) != 0) - } - - /// Returns the unparsed export directory. - /// - /// `data` must be the entire file data. - pub fn export_directory>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let export_data = data_dir.data(data, sections)?; - ExportTable::parse_directory(export_data).map(Some) - } - - /// Returns the partially parsed export directory. - /// - /// `data` must be the entire file data. - pub fn export_table>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result>> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_EXPORT) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let export_va = data_dir.virtual_address.get(LE); - let export_data = data_dir.data(data, sections)?; - ExportTable::parse(export_data, export_va).map(Some) - } - - /// Returns the partially parsed import directory. - /// - /// `data` must be the entire file data. - pub fn import_table>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result>> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_IMPORT) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let import_va = data_dir.virtual_address.get(LE); - let (section_data, section_va) = sections - .pe_data_containing(data, import_va) - .read_error("Invalid import data dir virtual address")?; - Ok(Some(ImportTable::new(section_data, section_va, import_va))) - } - - /// Returns the partially parsed delay-load import directory. - /// - /// `data` must be the entire file data. - pub fn delay_load_import_table>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result>> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let import_va = data_dir.virtual_address.get(LE); - let (section_data, section_va) = sections - .pe_data_containing(data, import_va) - .read_error("Invalid import data dir virtual address")?; - Ok(Some(DelayLoadImportTable::new( - section_data, - section_va, - import_va, - ))) - } - - /// Returns the blocks in the base relocation directory. - /// - /// `data` must be the entire file data. - pub fn relocation_blocks>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result>> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_BASERELOC) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let reloc_data = data_dir.data(data, sections)?; - Ok(Some(RelocationBlockIterator::new(reloc_data))) - } - - /// Returns the resource directory. - /// - /// `data` must be the entire file data. - pub fn resource_directory>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result>> { - let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_RESOURCE) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let rsrc_data = data_dir.data(data, sections)?; - Ok(Some(ResourceDirectory::new(rsrc_data))) - } -} - -impl pe::ImageDataDirectory { - /// Return the virtual address range of this directory entry. - pub fn address_range(&self) -> (u32, u32) { - (self.virtual_address.get(LE), self.size.get(LE)) - } - - /// Return the file offset and size of this directory entry. - /// - /// This function has some limitations: - /// - It requires that the data is contained in a single section. - /// - It uses the size field of the directory entry, which is - /// not desirable for all data directories. - /// - It uses the `virtual_address` of the directory entry as an address, - /// which is not valid for `IMAGE_DIRECTORY_ENTRY_SECURITY`. - pub fn file_range(&self, sections: &SectionTable<'_>) -> Result<(u32, u32)> { - let (offset, section_size) = sections - .pe_file_range_at(self.virtual_address.get(LE)) - .read_error("Invalid data dir virtual address")?; - let size = self.size.get(LE); - if size > section_size { - return Err(Error("Invalid data dir size")); - } - Ok((offset, size)) - } - - /// Get the data referenced by this directory entry. - /// - /// This function has some limitations: - /// - It requires that the data is contained in a single section. - /// - It uses the size field of the directory entry, which is - /// not desirable for all data directories. - /// - It uses the `virtual_address` of the directory entry as an address, - /// which is not valid for `IMAGE_DIRECTORY_ENTRY_SECURITY`. - pub fn data<'data, R: ReadRef<'data>>( - &self, - data: R, - sections: &SectionTable<'data>, - ) -> Result<&'data [u8]> { - sections - .pe_data_at(data, self.virtual_address.get(LE)) - .read_error("Invalid data dir virtual address")? - .get(..self.size.get(LE) as usize) - .read_error("Invalid data dir size") - } -} diff --git a/vendor/object/src/read/pe/export.rs b/vendor/object/src/read/pe/export.rs deleted file mode 100644 index 1aba844..0000000 --- a/vendor/object/src/read/pe/export.rs +++ /dev/null @@ -1,333 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; - -use crate::read::{ByteString, Bytes, Error, ReadError, ReadRef, Result}; -use crate::{pe, LittleEndian as LE, U16Bytes, U32Bytes}; - -/// Where an export is pointing to. -#[derive(Clone, Copy)] -pub enum ExportTarget<'data> { - /// The address of the export, relative to the image base. - Address(u32), - /// Forwarded to an export ordinal in another DLL. - /// - /// This gives the name of the DLL, and the ordinal. - ForwardByOrdinal(&'data [u8], u32), - /// Forwarded to an export name in another DLL. - /// - /// This gives the name of the DLL, and the export name. - ForwardByName(&'data [u8], &'data [u8]), -} - -impl<'data> ExportTarget<'data> { - /// Returns true if the target is an address. - pub fn is_address(&self) -> bool { - match self { - ExportTarget::Address(_) => true, - _ => false, - } - } - - /// Returns true if the export is forwarded to another DLL. - pub fn is_forward(&self) -> bool { - !self.is_address() - } -} - -/// An export from a PE file. -/// -/// There are multiple kinds of PE exports (with or without a name, and local or forwarded). -#[derive(Clone, Copy)] -pub struct Export<'data> { - /// The ordinal of the export. - /// - /// These are sequential, starting at a base specified in the DLL. - pub ordinal: u32, - /// The name of the export, if known. - pub name: Option<&'data [u8]>, - /// The target of this export. - pub target: ExportTarget<'data>, -} - -impl<'a> Debug for Export<'a> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> { - f.debug_struct("Export") - .field("ordinal", &self.ordinal) - .field("name", &self.name.map(ByteString)) - .field("target", &self.target) - .finish() - } -} - -impl<'a> Debug for ExportTarget<'a> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> { - match self { - ExportTarget::Address(address) => write!(f, "Address({:#x})", address), - ExportTarget::ForwardByOrdinal(library, ordinal) => write!( - f, - "ForwardByOrdinal({:?}.#{})", - ByteString(library), - ordinal - ), - ExportTarget::ForwardByName(library, name) => write!( - f, - "ForwardByName({:?}.{:?})", - ByteString(library), - ByteString(name) - ), - } - } -} - -/// A partially parsed PE export table. -/// -/// Returned by [`DataDirectories::export_table`](super::DataDirectories::export_table). -#[derive(Debug, Clone)] -pub struct ExportTable<'data> { - data: Bytes<'data>, - virtual_address: u32, - directory: &'data pe::ImageExportDirectory, - addresses: &'data [U32Bytes], - names: &'data [U32Bytes], - name_ordinals: &'data [U16Bytes], -} - -impl<'data> ExportTable<'data> { - /// Parse the export table given its section data and address. - pub fn parse(data: &'data [u8], virtual_address: u32) -> Result { - let directory = Self::parse_directory(data)?; - let data = Bytes(data); - - let mut addresses = &[][..]; - let address_of_functions = directory.address_of_functions.get(LE); - if address_of_functions != 0 { - addresses = data - .read_slice_at::>( - address_of_functions.wrapping_sub(virtual_address) as usize, - directory.number_of_functions.get(LE) as usize, - ) - .read_error("Invalid PE export address table")?; - } - - let mut names = &[][..]; - let mut name_ordinals = &[][..]; - let address_of_names = directory.address_of_names.get(LE); - let address_of_name_ordinals = directory.address_of_name_ordinals.get(LE); - if address_of_names != 0 { - if address_of_name_ordinals == 0 { - return Err(Error("Missing PE export ordinal table")); - } - - let number = directory.number_of_names.get(LE) as usize; - names = data - .read_slice_at::>( - address_of_names.wrapping_sub(virtual_address) as usize, - number, - ) - .read_error("Invalid PE export name pointer table")?; - name_ordinals = data - .read_slice_at::>( - address_of_name_ordinals.wrapping_sub(virtual_address) as usize, - number, - ) - .read_error("Invalid PE export ordinal table")?; - } - - Ok(ExportTable { - data, - virtual_address, - directory, - addresses, - names, - name_ordinals, - }) - } - - /// Parse the export directory given its section data. - pub fn parse_directory(data: &'data [u8]) -> Result<&'data pe::ImageExportDirectory> { - data.read_at::(0) - .read_error("Invalid PE export dir size") - } - - /// Returns the header of the export table. - pub fn directory(&self) -> &'data pe::ImageExportDirectory { - self.directory - } - - /// Returns the base value of ordinals. - /// - /// Adding this to an address index will give an ordinal. - pub fn ordinal_base(&self) -> u32 { - self.directory.base.get(LE) - } - - /// Returns the unparsed address table. - /// - /// An address table entry may be a local address, or the address of a forwarded export entry. - /// See [`Self::is_forward`] and [`Self::target_from_address`]. - pub fn addresses(&self) -> &'data [U32Bytes] { - self.addresses - } - - /// Returns the unparsed name pointer table. - /// - /// A name pointer table entry can be used with [`Self::name_from_pointer`]. - pub fn name_pointers(&self) -> &'data [U32Bytes] { - self.names - } - - /// Returns the unparsed ordinal table. - /// - /// An ordinal table entry is a 0-based index into the address table. - /// See [`Self::address_by_index`] and [`Self::target_by_index`]. - pub fn name_ordinals(&self) -> &'data [U16Bytes] { - self.name_ordinals - } - - /// Returns an iterator for the entries in the name pointer table and ordinal table. - /// - /// A name pointer table entry can be used with [`Self::name_from_pointer`]. - /// - /// An ordinal table entry is a 0-based index into the address table. - /// See [`Self::address_by_index`] and [`Self::target_by_index`]. - pub fn name_iter(&self) -> impl Iterator + 'data { - self.names - .iter() - .map(|x| x.get(LE)) - .zip(self.name_ordinals.iter().map(|x| x.get(LE))) - } - - /// Returns the export address table entry at the given address index. - /// - /// This may be a local address, or the address of a forwarded export entry. - /// See [`Self::is_forward`] and [`Self::target_from_address`]. - /// - /// `index` is a 0-based index into the export address table. - pub fn address_by_index(&self, index: u32) -> Result { - Ok(self - .addresses - .get(index as usize) - .read_error("Invalid PE export address index")? - .get(LE)) - } - - /// Returns the export address table entry at the given ordinal. - /// - /// This may be a local address, or the address of a forwarded export entry. - /// See [`Self::is_forward`] and [`Self::target_from_address`]. - pub fn address_by_ordinal(&self, ordinal: u32) -> Result { - self.address_by_index(ordinal.wrapping_sub(self.ordinal_base())) - } - - /// Returns the target of the export at the given address index. - /// - /// `index` is a 0-based index into the export address table. - pub fn target_by_index(&self, index: u32) -> Result> { - self.target_from_address(self.address_by_index(index)?) - } - - /// Returns the target of the export at the given ordinal. - pub fn target_by_ordinal(&self, ordinal: u32) -> Result> { - self.target_from_address(self.address_by_ordinal(ordinal)?) - } - - /// Convert an export address table entry into a target. - pub fn target_from_address(&self, address: u32) -> Result> { - Ok(if let Some(forward) = self.forward_string(address)? { - let i = forward - .iter() - .position(|x| *x == b'.') - .read_error("Missing PE forwarded export separator")?; - let library = &forward[..i]; - match &forward[i + 1..] { - [b'#', digits @ ..] => { - let ordinal = - parse_ordinal(digits).read_error("Invalid PE forwarded export ordinal")?; - ExportTarget::ForwardByOrdinal(library, ordinal) - } - [] => { - return Err(Error("Missing PE forwarded export name")); - } - name => ExportTarget::ForwardByName(library, name), - } - } else { - ExportTarget::Address(address) - }) - } - - fn forward_offset(&self, address: u32) -> Option { - let offset = address.wrapping_sub(self.virtual_address) as usize; - if offset < self.data.len() { - Some(offset) - } else { - None - } - } - - /// Return true if the export address table entry is a forward. - pub fn is_forward(&self, address: u32) -> bool { - self.forward_offset(address).is_some() - } - - /// Return the forward string if the export address table entry is a forward. - pub fn forward_string(&self, address: u32) -> Result> { - if let Some(offset) = self.forward_offset(address) { - self.data - .read_string_at(offset) - .read_error("Invalid PE forwarded export address") - .map(Some) - } else { - Ok(None) - } - } - - /// Convert an export name pointer table entry into a name. - pub fn name_from_pointer(&self, name_pointer: u32) -> Result<&'data [u8]> { - let offset = name_pointer.wrapping_sub(self.virtual_address); - self.data - .read_string_at(offset as usize) - .read_error("Invalid PE export name pointer") - } - - /// Returns the parsed exports in this table. - pub fn exports(&self) -> Result>> { - // First, let's list all exports. - let mut exports = Vec::new(); - let ordinal_base = self.ordinal_base(); - for (i, address) in self.addresses.iter().enumerate() { - // Convert from an array index to an ordinal. - let ordinal = ordinal_base.wrapping_add(i as u32); - let target = self.target_from_address(address.get(LE))?; - exports.push(Export { - ordinal, - target, - // Might be populated later. - name: None, - }); - } - - // Now, check whether some (or all) of them have an associated name. - // `ordinal_index` is a 0-based index into `addresses`. - for (name_pointer, ordinal_index) in self.name_iter() { - let name = self.name_from_pointer(name_pointer)?; - exports - .get_mut(ordinal_index as usize) - .read_error("Invalid PE export ordinal")? - .name = Some(name); - } - - Ok(exports) - } -} - -fn parse_ordinal(digits: &[u8]) -> Option { - if digits.is_empty() { - return None; - } - let mut result: u32 = 0; - for &c in digits { - let x = (c as char).to_digit(10)?; - result = result.checked_mul(10)?.checked_add(x)?; - } - Some(result) -} diff --git a/vendor/object/src/read/pe/file.rs b/vendor/object/src/read/pe/file.rs deleted file mode 100644 index 5372bdd..0000000 --- a/vendor/object/src/read/pe/file.rs +++ /dev/null @@ -1,1050 +0,0 @@ -use alloc::vec::Vec; -use core::fmt::Debug; -use core::{mem, str}; - -use core::convert::TryInto; - -use crate::read::coff::{CoffCommon, CoffSymbol, CoffSymbolIterator, CoffSymbolTable, SymbolTable}; -use crate::read::{ - self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator, - Object, ObjectComdat, ObjectKind, ReadError, ReadRef, Result, SectionIndex, SymbolIndex, -}; -use crate::{pe, ByteString, Bytes, CodeView, LittleEndian as LE, Pod, SubArchitecture, U32}; - -use super::{ - DataDirectories, ExportTable, ImageThunkData, ImportTable, PeSection, PeSectionIterator, - PeSegment, PeSegmentIterator, RichHeaderInfo, SectionTable, -}; - -/// A PE32 (32-bit) image file. -/// -/// This is a file that starts with [`pe::ImageNtHeaders32`], and corresponds -/// to [`crate::FileKind::Pe32`]. -pub type PeFile32<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders32, R>; -/// A PE32+ (64-bit) image file. -/// -/// This is a file that starts with [`pe::ImageNtHeaders64`], and corresponds -/// to [`crate::FileKind::Pe64`]. -pub type PeFile64<'data, R = &'data [u8]> = PeFile<'data, pe::ImageNtHeaders64, R>; - -/// A PE image file. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct PeFile<'data, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - pub(super) dos_header: &'data pe::ImageDosHeader, - pub(super) nt_headers: &'data Pe, - pub(super) data_directories: DataDirectories<'data>, - pub(super) common: CoffCommon<'data, R>, - pub(super) data: R, -} - -impl<'data, Pe, R> PeFile<'data, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - /// Parse the raw PE file data. - pub fn parse(data: R) -> Result { - let dos_header = pe::ImageDosHeader::parse(data)?; - let mut offset = dos_header.nt_headers_offset().into(); - let (nt_headers, data_directories) = Pe::parse(data, &mut offset)?; - let sections = nt_headers.sections(data, offset)?; - let coff_symbols = nt_headers.symbols(data); - let image_base = nt_headers.optional_header().image_base(); - - Ok(PeFile { - dos_header, - nt_headers, - data_directories, - common: CoffCommon { - sections, - // The PE file format deprecates the COFF symbol table (https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-file-header-object-and-image) - // We do not want to prevent parsing the rest of the PE file for a corrupt COFF header, but rather return an empty symbol table - symbols: coff_symbols.unwrap_or_default(), - image_base, - }, - data, - }) - } - - /// Returns this binary data. - pub fn data(&self) -> R { - self.data - } - - /// Return the DOS header of this file. - pub fn dos_header(&self) -> &'data pe::ImageDosHeader { - self.dos_header - } - - /// Return the NT Headers of this file. - pub fn nt_headers(&self) -> &'data Pe { - self.nt_headers - } - - /// Returns information about the rich header of this file (if any). - pub fn rich_header_info(&self) -> Option> { - RichHeaderInfo::parse(self.data, self.dos_header.nt_headers_offset().into()) - } - - /// Returns the section table of this binary. - pub fn section_table(&self) -> SectionTable<'data> { - self.common.sections - } - - /// Returns the data directories of this file. - pub fn data_directories(&self) -> DataDirectories<'data> { - self.data_directories - } - - /// Returns the data directory at the given index. - pub fn data_directory(&self, id: usize) -> Option<&'data pe::ImageDataDirectory> { - self.data_directories.get(id) - } - - /// Returns the export table of this file. - /// - /// The export table is located using the data directory. - pub fn export_table(&self) -> Result>> { - self.data_directories - .export_table(self.data, &self.common.sections) - } - - /// Returns the import table of this file. - /// - /// The import table is located using the data directory. - pub fn import_table(&self) -> Result>> { - self.data_directories - .import_table(self.data, &self.common.sections) - } - - pub(super) fn section_alignment(&self) -> u64 { - u64::from(self.nt_headers.optional_header().section_alignment()) - } -} - -impl<'data, Pe, R> read::private::Sealed for PeFile<'data, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Pe, R> Object<'data, 'file> for PeFile<'data, Pe, R> -where - 'data: 'file, - Pe: ImageNtHeaders, - R: 'file + ReadRef<'data>, -{ - type Segment = PeSegment<'data, 'file, Pe, R>; - type SegmentIterator = PeSegmentIterator<'data, 'file, Pe, R>; - type Section = PeSection<'data, 'file, Pe, R>; - type SectionIterator = PeSectionIterator<'data, 'file, Pe, R>; - type Comdat = PeComdat<'data, 'file, Pe, R>; - type ComdatIterator = PeComdatIterator<'data, 'file, Pe, R>; - type Symbol = CoffSymbol<'data, 'file, R>; - type SymbolIterator = CoffSymbolIterator<'data, 'file, R>; - type SymbolTable = CoffSymbolTable<'data, 'file, R>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - fn architecture(&self) -> Architecture { - match self.nt_headers.file_header().machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm, - pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => Architecture::Aarch64, - pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386, - pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64, - _ => Architecture::Unknown, - } - } - - fn sub_architecture(&self) -> Option { - match self.nt_headers.file_header().machine.get(LE) { - pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC), - _ => None, - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - // Only little endian is supported. - true - } - - #[inline] - fn is_64(&self) -> bool { - self.nt_headers.is_type_64() - } - - fn kind(&self) -> ObjectKind { - let characteristics = self.nt_headers.file_header().characteristics.get(LE); - if characteristics & pe::IMAGE_FILE_DLL != 0 { - ObjectKind::Dynamic - } else if characteristics & pe::IMAGE_FILE_SYSTEM != 0 { - ObjectKind::Unknown - } else { - ObjectKind::Executable - } - } - - fn segments(&'file self) -> PeSegmentIterator<'data, 'file, Pe, R> { - PeSegmentIterator { - file: self, - iter: self.common.sections.iter(), - } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - self.common - .sections - .section_by_name(self.common.symbols.strings(), section_name) - .map(|(index, section)| PeSection { - file: self, - index: SectionIndex(index), - section, - }) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> Result> { - let section = self.common.sections.section(index.0)?; - Ok(PeSection { - file: self, - index, - section, - }) - } - - fn sections(&'file self) -> PeSectionIterator<'data, 'file, Pe, R> { - PeSectionIterator { - file: self, - iter: self.common.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> PeComdatIterator<'data, 'file, Pe, R> { - PeComdatIterator { file: self } - } - - fn symbol_by_index(&'file self, index: SymbolIndex) -> Result> { - let symbol = self.common.symbols.symbol(index.0)?; - Ok(CoffSymbol { - file: &self.common, - index, - symbol, - }) - } - - fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> { - CoffSymbolIterator { - file: &self.common, - index: 0, - } - } - - fn symbol_table(&'file self) -> Option> { - Some(CoffSymbolTable { file: &self.common }) - } - - fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file, R> { - CoffSymbolIterator { - file: &self.common, - // Hack: don't return any. - index: self.common.symbols.len(), - } - } - - fn dynamic_symbol_table(&'file self) -> Option> { - None - } - - fn dynamic_relocations(&'file self) -> Option { - None - } - - fn imports(&self) -> Result>> { - let mut imports = Vec::new(); - if let Some(import_table) = self.import_table()? { - let mut import_descs = import_table.descriptors()?; - while let Some(import_desc) = import_descs.next()? { - let library = import_table.name(import_desc.name.get(LE))?; - let mut first_thunk = import_desc.original_first_thunk.get(LE); - if first_thunk == 0 { - first_thunk = import_desc.first_thunk.get(LE); - } - let mut thunks = import_table.thunks(first_thunk)?; - while let Some(thunk) = thunks.next::()? { - if !thunk.is_ordinal() { - let (_hint, name) = import_table.hint_name(thunk.address())?; - imports.push(Import { - library: ByteString(library), - name: ByteString(name), - }); - } - } - } - } - Ok(imports) - } - - fn exports(&self) -> Result>> { - let mut exports = Vec::new(); - if let Some(export_table) = self.export_table()? { - for (name_pointer, address_index) in export_table.name_iter() { - let name = export_table.name_from_pointer(name_pointer)?; - let address = export_table.address_by_index(address_index.into())?; - if !export_table.is_forward(address) { - exports.push(Export { - name: ByteString(name), - address: self.common.image_base.wrapping_add(address.into()), - }) - } - } - } - Ok(exports) - } - - fn pdb_info(&self) -> Result>> { - let data_dir = match self.data_directory(pe::IMAGE_DIRECTORY_ENTRY_DEBUG) { - Some(data_dir) => data_dir, - None => return Ok(None), - }; - let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?; - let debug_data_size = data_dir.size.get(LE) as usize; - - let count = debug_data_size / mem::size_of::(); - let rem = debug_data_size % mem::size_of::(); - if rem != 0 || count < 1 { - return Err(Error("Invalid PE debug dir size")); - } - - let debug_dirs = debug_data - .read_slice_at::(0, count) - .read_error("Invalid PE debug dir size")?; - - for debug_dir in debug_dirs { - if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW { - continue; - } - - let info = self - .data - .read_slice_at::( - debug_dir.pointer_to_raw_data.get(LE) as u64, - debug_dir.size_of_data.get(LE) as usize, - ) - .read_error("Invalid CodeView Info address")?; - - let mut info = Bytes(info); - - let sig = info - .read_bytes(4) - .read_error("Invalid CodeView signature")?; - if sig.0 != b"RSDS" { - continue; - } - - let guid: [u8; 16] = info - .read_bytes(16) - .read_error("Invalid CodeView GUID")? - .0 - .try_into() - .unwrap(); - - let age = info.read::>().read_error("Invalid CodeView Age")?; - - let path = info - .read_string() - .read_error("Invalid CodeView file path")?; - - return Ok(Some(CodeView { - path: ByteString(path), - guid, - age: age.get(LE), - })); - } - Ok(None) - } - - fn has_debug_symbols(&self) -> bool { - self.section_by_name(".debug_info").is_some() - } - - fn relative_address_base(&self) -> u64 { - self.common.image_base - } - - fn entry(&self) -> u64 { - u64::from(self.nt_headers.optional_header().address_of_entry_point()) - .wrapping_add(self.common.image_base) - } - - fn flags(&self) -> FileFlags { - FileFlags::Coff { - characteristics: self.nt_headers.file_header().characteristics.get(LE), - } - } -} - -/// An iterator for the COMDAT section groups in a [`PeFile32`]. -pub type PeComdatIterator32<'data, 'file, R = &'data [u8]> = - PeComdatIterator<'data, 'file, pe::ImageNtHeaders32, R>; -/// An iterator for the COMDAT section groups in a [`PeFile64`]. -pub type PeComdatIterator64<'data, 'file, R = &'data [u8]> = - PeComdatIterator<'data, 'file, pe::ImageNtHeaders64, R>; - -/// An iterator for the COMDAT section groups in a [`PeFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct PeComdatIterator<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file PeFile<'data, Pe, R>, -} - -impl<'data, 'file, Pe, R> Iterator for PeComdatIterator<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type Item = PeComdat<'data, 'file, Pe, R>; - - #[inline] - fn next(&mut self) -> Option { - None - } -} - -/// A COMDAT section group in a [`PeFile32`]. -pub type PeComdat32<'data, 'file, R = &'data [u8]> = - PeComdat<'data, 'file, pe::ImageNtHeaders32, R>; -/// A COMDAT section group in a [`PeFile64`]. -pub type PeComdat64<'data, 'file, R = &'data [u8]> = - PeComdat<'data, 'file, pe::ImageNtHeaders64, R>; - -/// A COMDAT section group in a [`PeFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct PeComdat<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file PeFile<'data, Pe, R>, -} - -impl<'data, 'file, Pe, R> read::private::Sealed for PeComdat<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Pe, R> ObjectComdat<'data> for PeComdat<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type SectionIterator = PeComdatSectionIterator<'data, 'file, Pe, R>; - - #[inline] - fn kind(&self) -> ComdatKind { - unreachable!(); - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - unreachable!(); - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - unreachable!(); - } - - #[inline] - fn name(&self) -> Result<&str> { - unreachable!(); - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - unreachable!(); - } -} - -/// An iterator for the sections in a COMDAT section group in a [`PeFile32`]. -pub type PeComdatSectionIterator32<'data, 'file, R = &'data [u8]> = - PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>; -/// An iterator for the sections in a COMDAT section group in a [`PeFile64`]. -pub type PeComdatSectionIterator64<'data, 'file, R = &'data [u8]> = - PeComdatSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>; - -/// An iterator for the sections in a COMDAT section group in a [`PeFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct PeComdatSectionIterator<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file PeFile<'data, Pe, R>, -} - -impl<'data, 'file, Pe, R> Iterator for PeComdatSectionIterator<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option { - None - } -} - -impl pe::ImageDosHeader { - /// Read the DOS header. - /// - /// Also checks that the `e_magic` field in the header is valid. - pub fn parse<'data, R: ReadRef<'data>>(data: R) -> read::Result<&'data Self> { - // DOS header comes first. - let dos_header = data - .read_at::(0) - .read_error("Invalid DOS header size or alignment")?; - if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE { - return Err(Error("Invalid DOS magic")); - } - Ok(dos_header) - } - - /// Return the file offset of the nt_headers. - #[inline] - pub fn nt_headers_offset(&self) -> u32 { - self.e_lfanew.get(LE) - } -} - -/// Find the optional header and read its `magic` field. -/// -/// It can be useful to know this magic value before trying to -/// fully parse the NT headers. -pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result { - let dos_header = pe::ImageDosHeader::parse(data)?; - // NT headers are at an offset specified in the DOS header. - let offset = dos_header.nt_headers_offset().into(); - // It doesn't matter which NT header type is used for the purpose - // of reading the optional header magic. - let nt_headers = data - .read_at::(offset) - .read_error("Invalid NT headers offset, size, or alignment")?; - if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE { - return Err(Error("Invalid PE magic")); - } - Ok(nt_headers.optional_header().magic()) -} - -/// A trait for generic access to [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`]. -#[allow(missing_docs)] -pub trait ImageNtHeaders: Debug + Pod { - type ImageOptionalHeader: ImageOptionalHeader; - type ImageThunkData: ImageThunkData; - - /// Return true if this type is a 64-bit header. - /// - /// This is a property of the type, not a value in the header data. - fn is_type_64(&self) -> bool; - - /// Return true if the magic field in the optional header is valid. - fn is_valid_optional_magic(&self) -> bool; - - /// Return the signature - fn signature(&self) -> u32; - - /// Return the file header. - fn file_header(&self) -> &pe::ImageFileHeader; - - /// Return the optional header. - fn optional_header(&self) -> &Self::ImageOptionalHeader; - - // Provided methods. - - /// Read the NT headers, including the data directories. - /// - /// `data` must be for the entire file. - /// - /// `offset` must be headers offset, which can be obtained from [`pe::ImageDosHeader::nt_headers_offset`]. - /// It is updated to point after the optional header, which is where the section headers are located. - /// - /// Also checks that the `signature` and `magic` fields in the headers are valid. - fn parse<'data, R: ReadRef<'data>>( - data: R, - offset: &mut u64, - ) -> read::Result<(&'data Self, DataDirectories<'data>)> { - // Note that this does not include the data directories in the optional header. - let nt_headers = data - .read::(offset) - .read_error("Invalid PE headers offset or size")?; - if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE { - return Err(Error("Invalid PE magic")); - } - if !nt_headers.is_valid_optional_magic() { - return Err(Error("Invalid PE optional header magic")); - } - - // Read the rest of the optional header, and then read the data directories from that. - let optional_data_size = - u64::from(nt_headers.file_header().size_of_optional_header.get(LE)) - .checked_sub(mem::size_of::() as u64) - .read_error("PE optional header size is too small")?; - let optional_data = data - .read_bytes(offset, optional_data_size) - .read_error("Invalid PE optional header size")?; - let data_directories = DataDirectories::parse( - optional_data, - nt_headers.optional_header().number_of_rva_and_sizes(), - )?; - - Ok((nt_headers, data_directories)) - } - - /// Read the section table. - /// - /// `data` must be for the entire file. - /// `offset` must be after the optional file header. - #[inline] - fn sections<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: u64, - ) -> read::Result> { - SectionTable::parse(self.file_header(), data, offset) - } - - /// Read the COFF symbol table and string table. - /// - /// `data` must be the entire file data. - #[inline] - fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result> { - SymbolTable::parse(self.file_header(), data) - } -} - -/// A trait for generic access to [`pe::ImageOptionalHeader32`] and [`pe::ImageOptionalHeader64`]. -#[allow(missing_docs)] -pub trait ImageOptionalHeader: Debug + Pod { - // Standard fields. - fn magic(&self) -> u16; - fn major_linker_version(&self) -> u8; - fn minor_linker_version(&self) -> u8; - fn size_of_code(&self) -> u32; - fn size_of_initialized_data(&self) -> u32; - fn size_of_uninitialized_data(&self) -> u32; - fn address_of_entry_point(&self) -> u32; - fn base_of_code(&self) -> u32; - fn base_of_data(&self) -> Option; - - // NT additional fields. - fn image_base(&self) -> u64; - fn section_alignment(&self) -> u32; - fn file_alignment(&self) -> u32; - fn major_operating_system_version(&self) -> u16; - fn minor_operating_system_version(&self) -> u16; - fn major_image_version(&self) -> u16; - fn minor_image_version(&self) -> u16; - fn major_subsystem_version(&self) -> u16; - fn minor_subsystem_version(&self) -> u16; - fn win32_version_value(&self) -> u32; - fn size_of_image(&self) -> u32; - fn size_of_headers(&self) -> u32; - fn check_sum(&self) -> u32; - fn subsystem(&self) -> u16; - fn dll_characteristics(&self) -> u16; - fn size_of_stack_reserve(&self) -> u64; - fn size_of_stack_commit(&self) -> u64; - fn size_of_heap_reserve(&self) -> u64; - fn size_of_heap_commit(&self) -> u64; - fn loader_flags(&self) -> u32; - fn number_of_rva_and_sizes(&self) -> u32; -} - -impl ImageNtHeaders for pe::ImageNtHeaders32 { - type ImageOptionalHeader = pe::ImageOptionalHeader32; - type ImageThunkData = pe::ImageThunkData32; - - #[inline] - fn is_type_64(&self) -> bool { - false - } - - #[inline] - fn is_valid_optional_magic(&self) -> bool { - self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC - } - - #[inline] - fn signature(&self) -> u32 { - self.signature.get(LE) - } - - #[inline] - fn file_header(&self) -> &pe::ImageFileHeader { - &self.file_header - } - - #[inline] - fn optional_header(&self) -> &Self::ImageOptionalHeader { - &self.optional_header - } -} - -impl ImageOptionalHeader for pe::ImageOptionalHeader32 { - #[inline] - fn magic(&self) -> u16 { - self.magic.get(LE) - } - - #[inline] - fn major_linker_version(&self) -> u8 { - self.major_linker_version - } - - #[inline] - fn minor_linker_version(&self) -> u8 { - self.minor_linker_version - } - - #[inline] - fn size_of_code(&self) -> u32 { - self.size_of_code.get(LE) - } - - #[inline] - fn size_of_initialized_data(&self) -> u32 { - self.size_of_initialized_data.get(LE) - } - - #[inline] - fn size_of_uninitialized_data(&self) -> u32 { - self.size_of_uninitialized_data.get(LE) - } - - #[inline] - fn address_of_entry_point(&self) -> u32 { - self.address_of_entry_point.get(LE) - } - - #[inline] - fn base_of_code(&self) -> u32 { - self.base_of_code.get(LE) - } - - #[inline] - fn base_of_data(&self) -> Option { - Some(self.base_of_data.get(LE)) - } - - #[inline] - fn image_base(&self) -> u64 { - self.image_base.get(LE).into() - } - - #[inline] - fn section_alignment(&self) -> u32 { - self.section_alignment.get(LE) - } - - #[inline] - fn file_alignment(&self) -> u32 { - self.file_alignment.get(LE) - } - - #[inline] - fn major_operating_system_version(&self) -> u16 { - self.major_operating_system_version.get(LE) - } - - #[inline] - fn minor_operating_system_version(&self) -> u16 { - self.minor_operating_system_version.get(LE) - } - - #[inline] - fn major_image_version(&self) -> u16 { - self.major_image_version.get(LE) - } - - #[inline] - fn minor_image_version(&self) -> u16 { - self.minor_image_version.get(LE) - } - - #[inline] - fn major_subsystem_version(&self) -> u16 { - self.major_subsystem_version.get(LE) - } - - #[inline] - fn minor_subsystem_version(&self) -> u16 { - self.minor_subsystem_version.get(LE) - } - - #[inline] - fn win32_version_value(&self) -> u32 { - self.win32_version_value.get(LE) - } - - #[inline] - fn size_of_image(&self) -> u32 { - self.size_of_image.get(LE) - } - - #[inline] - fn size_of_headers(&self) -> u32 { - self.size_of_headers.get(LE) - } - - #[inline] - fn check_sum(&self) -> u32 { - self.check_sum.get(LE) - } - - #[inline] - fn subsystem(&self) -> u16 { - self.subsystem.get(LE) - } - - #[inline] - fn dll_characteristics(&self) -> u16 { - self.dll_characteristics.get(LE) - } - - #[inline] - fn size_of_stack_reserve(&self) -> u64 { - self.size_of_stack_reserve.get(LE).into() - } - - #[inline] - fn size_of_stack_commit(&self) -> u64 { - self.size_of_stack_commit.get(LE).into() - } - - #[inline] - fn size_of_heap_reserve(&self) -> u64 { - self.size_of_heap_reserve.get(LE).into() - } - - #[inline] - fn size_of_heap_commit(&self) -> u64 { - self.size_of_heap_commit.get(LE).into() - } - - #[inline] - fn loader_flags(&self) -> u32 { - self.loader_flags.get(LE) - } - - #[inline] - fn number_of_rva_and_sizes(&self) -> u32 { - self.number_of_rva_and_sizes.get(LE) - } -} - -impl ImageNtHeaders for pe::ImageNtHeaders64 { - type ImageOptionalHeader = pe::ImageOptionalHeader64; - type ImageThunkData = pe::ImageThunkData64; - - #[inline] - fn is_type_64(&self) -> bool { - true - } - - #[inline] - fn is_valid_optional_magic(&self) -> bool { - self.optional_header.magic.get(LE) == pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC - } - - #[inline] - fn signature(&self) -> u32 { - self.signature.get(LE) - } - - #[inline] - fn file_header(&self) -> &pe::ImageFileHeader { - &self.file_header - } - - #[inline] - fn optional_header(&self) -> &Self::ImageOptionalHeader { - &self.optional_header - } -} - -impl ImageOptionalHeader for pe::ImageOptionalHeader64 { - #[inline] - fn magic(&self) -> u16 { - self.magic.get(LE) - } - - #[inline] - fn major_linker_version(&self) -> u8 { - self.major_linker_version - } - - #[inline] - fn minor_linker_version(&self) -> u8 { - self.minor_linker_version - } - - #[inline] - fn size_of_code(&self) -> u32 { - self.size_of_code.get(LE) - } - - #[inline] - fn size_of_initialized_data(&self) -> u32 { - self.size_of_initialized_data.get(LE) - } - - #[inline] - fn size_of_uninitialized_data(&self) -> u32 { - self.size_of_uninitialized_data.get(LE) - } - - #[inline] - fn address_of_entry_point(&self) -> u32 { - self.address_of_entry_point.get(LE) - } - - #[inline] - fn base_of_code(&self) -> u32 { - self.base_of_code.get(LE) - } - - #[inline] - fn base_of_data(&self) -> Option { - None - } - - #[inline] - fn image_base(&self) -> u64 { - self.image_base.get(LE) - } - - #[inline] - fn section_alignment(&self) -> u32 { - self.section_alignment.get(LE) - } - - #[inline] - fn file_alignment(&self) -> u32 { - self.file_alignment.get(LE) - } - - #[inline] - fn major_operating_system_version(&self) -> u16 { - self.major_operating_system_version.get(LE) - } - - #[inline] - fn minor_operating_system_version(&self) -> u16 { - self.minor_operating_system_version.get(LE) - } - - #[inline] - fn major_image_version(&self) -> u16 { - self.major_image_version.get(LE) - } - - #[inline] - fn minor_image_version(&self) -> u16 { - self.minor_image_version.get(LE) - } - - #[inline] - fn major_subsystem_version(&self) -> u16 { - self.major_subsystem_version.get(LE) - } - - #[inline] - fn minor_subsystem_version(&self) -> u16 { - self.minor_subsystem_version.get(LE) - } - - #[inline] - fn win32_version_value(&self) -> u32 { - self.win32_version_value.get(LE) - } - - #[inline] - fn size_of_image(&self) -> u32 { - self.size_of_image.get(LE) - } - - #[inline] - fn size_of_headers(&self) -> u32 { - self.size_of_headers.get(LE) - } - - #[inline] - fn check_sum(&self) -> u32 { - self.check_sum.get(LE) - } - - #[inline] - fn subsystem(&self) -> u16 { - self.subsystem.get(LE) - } - - #[inline] - fn dll_characteristics(&self) -> u16 { - self.dll_characteristics.get(LE) - } - - #[inline] - fn size_of_stack_reserve(&self) -> u64 { - self.size_of_stack_reserve.get(LE) - } - - #[inline] - fn size_of_stack_commit(&self) -> u64 { - self.size_of_stack_commit.get(LE) - } - - #[inline] - fn size_of_heap_reserve(&self) -> u64 { - self.size_of_heap_reserve.get(LE) - } - - #[inline] - fn size_of_heap_commit(&self) -> u64 { - self.size_of_heap_commit.get(LE) - } - - #[inline] - fn loader_flags(&self) -> u32 { - self.loader_flags.get(LE) - } - - #[inline] - fn number_of_rva_and_sizes(&self) -> u32 { - self.number_of_rva_and_sizes.get(LE) - } -} diff --git a/vendor/object/src/read/pe/import.rs b/vendor/object/src/read/pe/import.rs deleted file mode 100644 index 8e9a9a9..0000000 --- a/vendor/object/src/read/pe/import.rs +++ /dev/null @@ -1,337 +0,0 @@ -use core::fmt::Debug; -use core::mem; - -use crate::read::{Bytes, ReadError, Result}; -use crate::{pe, LittleEndian as LE, Pod, U16Bytes}; - -use super::ImageNtHeaders; - -/// Information for parsing a PE import table. -/// -/// Returned by [`DataDirectories::import_table`](super::DataDirectories::import_table). -#[derive(Debug, Clone)] -pub struct ImportTable<'data> { - section_data: Bytes<'data>, - section_address: u32, - import_address: u32, -} - -impl<'data> ImportTable<'data> { - /// Create a new import table parser. - /// - /// The import descriptors start at `import_address`. - /// The size declared in the `IMAGE_DIRECTORY_ENTRY_IMPORT` data directory is - /// ignored by the Windows loader, and so descriptors will be parsed until a null entry. - /// - /// `section_data` should be from the section containing `import_address`, and - /// `section_address` should be the address of that section. Pointers within the - /// descriptors and thunks may point to anywhere within the section data. - pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self { - ImportTable { - section_data: Bytes(section_data), - section_address, - import_address, - } - } - - /// Return an iterator for the import descriptors. - pub fn descriptors(&self) -> Result> { - let offset = self.import_address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import descriptor address")?; - Ok(ImportDescriptorIterator { data }) - } - - /// Return a library name given its address. - /// - /// This address may be from [`pe::ImageImportDescriptor::name`]. - pub fn name(&self, address: u32) -> Result<&'data [u8]> { - self.section_data - .read_string_at(address.wrapping_sub(self.section_address) as usize) - .read_error("Invalid PE import descriptor name") - } - - /// Return a list of thunks given its address. - /// - /// This address may be from [`pe::ImageImportDescriptor::original_first_thunk`] - /// or [`pe::ImageImportDescriptor::first_thunk`]. - pub fn thunks(&self, address: u32) -> Result> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import thunk table address")?; - Ok(ImportThunkList { data }) - } - - /// Parse a thunk. - pub fn import(&self, thunk: Pe::ImageThunkData) -> Result> { - if thunk.is_ordinal() { - Ok(Import::Ordinal(thunk.ordinal())) - } else { - let (hint, name) = self.hint_name(thunk.address())?; - Ok(Import::Name(hint, name)) - } - } - - /// Return the hint and name at the given address. - /// - /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`]. - /// - /// The hint is an index into the export name pointer table in the target library. - pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE import thunk address")?; - let hint = data - .read::>() - .read_error("Missing PE import thunk hint")? - .get(LE); - let name = data - .read_string() - .read_error("Missing PE import thunk name")?; - Ok((hint, name)) - } -} - -/// A fallible iterator for the descriptors in the import data directory. -#[derive(Debug, Clone)] -pub struct ImportDescriptorIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> ImportDescriptorIterator<'data> { - /// Return the next descriptor. - /// - /// Returns `Ok(None)` when a null descriptor is found. - pub fn next(&mut self) -> Result> { - let import_desc = self - .data - .read::() - .read_error("Missing PE null import descriptor")?; - if import_desc.is_null() { - Ok(None) - } else { - Ok(Some(import_desc)) - } - } -} - -/// A list of import thunks. -/// -/// These may be in the import lookup table, or the import address table. -#[derive(Debug, Clone)] -pub struct ImportThunkList<'data> { - data: Bytes<'data>, -} - -impl<'data> ImportThunkList<'data> { - /// Get the thunk at the given index. - pub fn get(&self, index: usize) -> Result { - let thunk = self - .data - .read_at(index * mem::size_of::()) - .read_error("Invalid PE import thunk index")?; - Ok(*thunk) - } - - /// Return the first thunk in the list, and update `self` to point after it. - /// - /// Returns `Ok(None)` when a null thunk is found. - pub fn next(&mut self) -> Result> { - let thunk = self - .data - .read::() - .read_error("Missing PE null import thunk")?; - if thunk.address() == 0 { - Ok(None) - } else { - Ok(Some(*thunk)) - } - } -} - -/// A parsed import thunk. -#[derive(Debug, Clone, Copy)] -pub enum Import<'data> { - /// Import by ordinal. - Ordinal(u16), - /// Import by name. - /// - /// Includes a hint for the index into the export name pointer table in the target library. - Name(u16, &'data [u8]), -} - -/// A trait for generic access to [`pe::ImageThunkData32`] and [`pe::ImageThunkData64`]. -#[allow(missing_docs)] -pub trait ImageThunkData: Debug + Pod { - /// Return the raw thunk value. - fn raw(self) -> u64; - - /// Returns true if the ordinal flag is set. - fn is_ordinal(self) -> bool; - - /// Return the ordinal portion of the thunk. - /// - /// Does not check the ordinal flag. - fn ordinal(self) -> u16; - - /// Return the RVA portion of the thunk. - /// - /// Does not check the ordinal flag. - fn address(self) -> u32; -} - -impl ImageThunkData for pe::ImageThunkData64 { - fn raw(self) -> u64 { - self.0.get(LE) - } - - fn is_ordinal(self) -> bool { - self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG64 != 0 - } - - fn ordinal(self) -> u16 { - self.0.get(LE) as u16 - } - - fn address(self) -> u32 { - self.0.get(LE) as u32 & 0x7fff_ffff - } -} - -impl ImageThunkData for pe::ImageThunkData32 { - fn raw(self) -> u64 { - self.0.get(LE).into() - } - - fn is_ordinal(self) -> bool { - self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG32 != 0 - } - - fn ordinal(self) -> u16 { - self.0.get(LE) as u16 - } - - fn address(self) -> u32 { - self.0.get(LE) & 0x7fff_ffff - } -} - -/// Information for parsing a PE delay-load import table. -/// -/// Returned by -/// [`DataDirectories::delay_load_import_table`](super::DataDirectories::delay_load_import_table). -#[derive(Debug, Clone)] -pub struct DelayLoadImportTable<'data> { - section_data: Bytes<'data>, - section_address: u32, - import_address: u32, -} - -impl<'data> DelayLoadImportTable<'data> { - /// Create a new delay load import table parser. - /// - /// The import descriptors start at `import_address`. - /// This table works in the same way the import table does: descriptors will be - /// parsed until a null entry. - /// - /// `section_data` should be from the section containing `import_address`, and - /// `section_address` should be the address of that section. Pointers within the - /// descriptors and thunks may point to anywhere within the section data. - pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self { - DelayLoadImportTable { - section_data: Bytes(section_data), - section_address, - import_address, - } - } - - /// Return an iterator for the import descriptors. - pub fn descriptors(&self) -> Result> { - let offset = self.import_address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay-load import descriptor address")?; - Ok(DelayLoadDescriptorIterator { data }) - } - - /// Return a library name given its address. - /// - /// This address may be from [`pe::ImageDelayloadDescriptor::dll_name_rva`]. - pub fn name(&self, address: u32) -> Result<&'data [u8]> { - self.section_data - .read_string_at(address.wrapping_sub(self.section_address) as usize) - .read_error("Invalid PE import descriptor name") - } - - /// Return a list of thunks given its address. - /// - /// This address may be from the INT, i.e. from - /// [`pe::ImageDelayloadDescriptor::import_name_table_rva`]. - /// - /// Please note that others RVA values from [`pe::ImageDelayloadDescriptor`] are used - /// by the delay loader at runtime to store values, and thus do not point inside the same - /// section as the INT. Calling this function on those addresses will fail. - pub fn thunks(&self, address: u32) -> Result> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay load import thunk table address")?; - Ok(ImportThunkList { data }) - } - - /// Parse a thunk. - pub fn import(&self, thunk: Pe::ImageThunkData) -> Result> { - if thunk.is_ordinal() { - Ok(Import::Ordinal(thunk.ordinal())) - } else { - let (hint, name) = self.hint_name(thunk.address())?; - Ok(Import::Name(hint, name)) - } - } - - /// Return the hint and name at the given address. - /// - /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`]. - /// - /// The hint is an index into the export name pointer table in the target library. - pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> { - let offset = address.wrapping_sub(self.section_address); - let mut data = self.section_data; - data.skip(offset as usize) - .read_error("Invalid PE delay load import thunk address")?; - let hint = data - .read::>() - .read_error("Missing PE delay load import thunk hint")? - .get(LE); - let name = data - .read_string() - .read_error("Missing PE delay load import thunk name")?; - Ok((hint, name)) - } -} - -/// A fallible iterator for the descriptors in the delay-load data directory. -#[derive(Debug, Clone)] -pub struct DelayLoadDescriptorIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> DelayLoadDescriptorIterator<'data> { - /// Return the next descriptor. - /// - /// Returns `Ok(None)` when a null descriptor is found. - pub fn next(&mut self) -> Result> { - let import_desc = self - .data - .read::() - .read_error("Missing PE null delay-load import descriptor")?; - if import_desc.is_null() { - Ok(None) - } else { - Ok(Some(import_desc)) - } - } -} diff --git a/vendor/object/src/read/pe/mod.rs b/vendor/object/src/read/pe/mod.rs deleted file mode 100644 index ab6011c..0000000 --- a/vendor/object/src/read/pe/mod.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Support for reading PE files. -//! -//! Traits are used to abstract over the difference between PE32 and PE32+. -//! The primary trait for this is [`ImageNtHeaders`]. -//! -//! ## High level API -//! -//! [`PeFile`] implements the [`Object`](crate::read::Object) trait for -//! PE files. [`PeFile`] is parameterised by [`ImageNtHeaders`] to allow -//! reading both PE32 and PE32+. There are type aliases for these parameters -//! ([`PeFile32`] and [`PeFile64`]). -//! -//! ## Low level API -//! -//! The [`ImageNtHeaders`] trait can be directly used to parse both -//! [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`]. -//! -//! ### Example for low level API -//! ```no_run -//! use object::pe; -//! use object::read::pe::ImageNtHeaders; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each section. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let dos_header = pe::ImageDosHeader::parse(&*data)?; -//! let mut offset = dos_header.nt_headers_offset().into(); -//! let (nt_headers, data_directories) = pe::ImageNtHeaders64::parse(&*data, &mut offset)?; -//! let sections = nt_headers.sections(&*data, offset)?; -//! let symbols = nt_headers.symbols(&*data)?; -//! for section in sections.iter() { -//! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?)); -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::pe; - -mod file; -pub use file::*; - -mod section; -pub use section::*; - -mod data_directory; -pub use data_directory::*; - -mod export; -pub use export::*; - -mod import; -pub use import::*; - -mod relocation; -pub use relocation::*; - -mod resource; -pub use resource::*; - -mod rich; -pub use rich::*; - -pub use super::coff::{SectionTable, SymbolTable}; diff --git a/vendor/object/src/read/pe/relocation.rs b/vendor/object/src/read/pe/relocation.rs deleted file mode 100644 index 77421b7..0000000 --- a/vendor/object/src/read/pe/relocation.rs +++ /dev/null @@ -1,92 +0,0 @@ -use core::slice; - -use crate::endian::{LittleEndian as LE, U16}; -use crate::pe; -use crate::read::{Bytes, Error, ReadError, Result}; - -/// An iterator over the relocation blocks in the `.reloc` section of a PE file. -/// -/// Returned by [`DataDirectories::relocation_blocks`](super::DataDirectories::relocation_blocks). -#[derive(Debug, Default, Clone, Copy)] -pub struct RelocationBlockIterator<'data> { - data: Bytes<'data>, -} - -impl<'data> RelocationBlockIterator<'data> { - /// Construct a new iterator from the data of the `.reloc` section. - pub fn new(data: &'data [u8]) -> Self { - RelocationBlockIterator { data: Bytes(data) } - } - - /// Read the next relocation page. - pub fn next(&mut self) -> Result>> { - if self.data.is_empty() { - return Ok(None); - } - let header = self - .data - .read::() - .read_error("Invalid PE reloc section size")?; - let virtual_address = header.virtual_address.get(LE); - let size = header.size_of_block.get(LE); - if size <= 8 || size & 3 != 0 { - return Err(Error("Invalid PE reloc block size")); - } - let count = (size - 8) / 2; - let relocs = self - .data - .read_slice::>(count as usize) - .read_error("Invalid PE reloc block size")? - .iter(); - Ok(Some(RelocationIterator { - virtual_address, - size, - relocs, - })) - } -} - -/// An iterator of the relocations in a block in the `.reloc` section of a PE file. -#[derive(Debug, Clone)] -pub struct RelocationIterator<'data> { - virtual_address: u32, - size: u32, - relocs: slice::Iter<'data, U16>, -} - -impl<'data> RelocationIterator<'data> { - /// Return the virtual address of the page that this block of relocations applies to. - pub fn virtual_address(&self) -> u32 { - self.virtual_address - } - - /// Return the size in bytes of this block of relocations. - pub fn size(&self) -> u32 { - self.size - } -} - -impl<'data> Iterator for RelocationIterator<'data> { - type Item = Relocation; - - fn next(&mut self) -> Option { - loop { - let reloc = self.relocs.next()?.get(LE); - if reloc != 0 { - return Some(Relocation { - virtual_address: self.virtual_address.wrapping_add((reloc & 0xfff) as u32), - typ: reloc >> 12, - }); - } - } - } -} - -/// A relocation in the `.reloc` section of a PE file. -#[derive(Debug, Default, Clone, Copy)] -pub struct Relocation { - /// The virtual address of the relocation. - pub virtual_address: u32, - /// One of the `pe::IMAGE_REL_BASED_*` constants. - pub typ: u16, -} diff --git a/vendor/object/src/read/pe/resource.rs b/vendor/object/src/read/pe/resource.rs deleted file mode 100644 index 331da3f..0000000 --- a/vendor/object/src/read/pe/resource.rs +++ /dev/null @@ -1,209 +0,0 @@ -use alloc::string::String; -use core::char; - -use crate::read::{ReadError, ReadRef, Result}; -use crate::{pe, LittleEndian as LE, U16Bytes}; - -/// The `.rsrc` section of a PE file. -/// -/// Returned by [`DataDirectories::resource_directory`](super::DataDirectories::resource_directory). -#[derive(Debug, Clone, Copy)] -pub struct ResourceDirectory<'data> { - data: &'data [u8], -} - -impl<'data> ResourceDirectory<'data> { - /// Construct from the data of the `.rsrc` section. - pub fn new(data: &'data [u8]) -> Self { - ResourceDirectory { data } - } - - /// Parses the root resource directory. - pub fn root(&self) -> Result> { - ResourceDirectoryTable::parse(self.data, 0) - } -} - -/// A table of resource entries. -#[derive(Debug, Clone)] -pub struct ResourceDirectoryTable<'data> { - /// The table header. - pub header: &'data pe::ImageResourceDirectory, - /// The table entries. - pub entries: &'data [pe::ImageResourceDirectoryEntry], -} - -impl<'data> ResourceDirectoryTable<'data> { - fn parse(data: &'data [u8], offset: u32) -> Result { - let mut offset = u64::from(offset); - let header = data - .read::(&mut offset) - .read_error("Invalid resource table header")?; - let entries_count = header.number_of_id_entries.get(LE) as usize - + header.number_of_named_entries.get(LE) as usize; - let entries = data - .read_slice::(&mut offset, entries_count) - .read_error("Invalid resource table entries")?; - Ok(Self { header, entries }) - } -} - -impl pe::ImageResourceDirectoryEntry { - /// Returns true if the entry has a name, rather than an ID. - pub fn has_name(&self) -> bool { - self.name_or_id.get(LE) & pe::IMAGE_RESOURCE_NAME_IS_STRING != 0 - } - - /// Returns the section offset of the name. - /// - /// Valid if `has_name()` returns true. - fn name(&self) -> ResourceName { - let offset = self.name_or_id.get(LE) & !pe::IMAGE_RESOURCE_NAME_IS_STRING; - ResourceName { offset } - } - - /// Returns the ID. - /// - /// Valid if `has_string_name()` returns false. - fn id(&self) -> u16 { - (self.name_or_id.get(LE) & 0x0000_FFFF) as u16 - } - - /// Returns the entry name - pub fn name_or_id(&self) -> ResourceNameOrId { - if self.has_name() { - ResourceNameOrId::Name(self.name()) - } else { - ResourceNameOrId::Id(self.id()) - } - } - - /// Returns true if the entry is a subtable. - pub fn is_table(&self) -> bool { - self.offset_to_data_or_directory.get(LE) & pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY != 0 - } - - /// Returns the section offset of the associated table or data. - pub fn data_offset(&self) -> u32 { - self.offset_to_data_or_directory.get(LE) & !pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY - } - - /// Returns the data associated to this directory entry. - pub fn data<'data>( - &self, - section: ResourceDirectory<'data>, - ) -> Result> { - if self.is_table() { - ResourceDirectoryTable::parse(section.data, self.data_offset()) - .map(ResourceDirectoryEntryData::Table) - } else { - section - .data - .read_at::(self.data_offset().into()) - .read_error("Invalid resource entry") - .map(ResourceDirectoryEntryData::Data) - } - } -} - -/// Data associated with a resource directory entry. -#[derive(Debug, Clone)] -pub enum ResourceDirectoryEntryData<'data> { - /// A subtable entry. - Table(ResourceDirectoryTable<'data>), - /// A resource data entry. - Data(&'data pe::ImageResourceDataEntry), -} - -impl<'data> ResourceDirectoryEntryData<'data> { - /// Converts to an option of table. - /// - /// Helper for iterator filtering. - pub fn table(self) -> Option> { - match self { - Self::Table(dir) => Some(dir), - _ => None, - } - } - - /// Converts to an option of data entry. - /// - /// Helper for iterator filtering. - pub fn data(self) -> Option<&'data pe::ImageResourceDataEntry> { - match self { - Self::Data(rsc) => Some(rsc), - _ => None, - } - } -} - -/// A resource name. -#[derive(Debug, Clone, Copy)] -pub struct ResourceName { - offset: u32, -} - -impl ResourceName { - /// Converts to a `String`. - pub fn to_string_lossy(&self, directory: ResourceDirectory<'_>) -> Result { - let d = self.data(directory)?.iter().map(|c| c.get(LE)); - - Ok(char::decode_utf16(d) - .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) - .collect::()) - } - - /// Returns the string unicode buffer. - pub fn data<'data>( - &self, - directory: ResourceDirectory<'data>, - ) -> Result<&'data [U16Bytes]> { - let mut offset = u64::from(self.offset); - let len = directory - .data - .read::>(&mut offset) - .read_error("Invalid resource name offset")?; - directory - .data - .read_slice::>(&mut offset, len.get(LE).into()) - .read_error("Invalid resource name length") - } - - /// Returns the string buffer as raw bytes. - pub fn raw_data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u8]> { - self.data(directory).map(crate::pod::bytes_of_slice) - } -} - -/// A resource name or ID. -/// -/// Can be either a string or a numeric ID. -#[derive(Debug)] -pub enum ResourceNameOrId { - /// A resource name. - Name(ResourceName), - /// A resource ID. - Id(u16), -} - -impl ResourceNameOrId { - /// Converts to an option of name. - /// - /// Helper for iterator filtering. - pub fn name(self) -> Option { - match self { - Self::Name(name) => Some(name), - _ => None, - } - } - - /// Converts to an option of ID. - /// - /// Helper for iterator filtering. - pub fn id(self) -> Option { - match self { - Self::Id(id) => Some(id), - _ => None, - } - } -} diff --git a/vendor/object/src/read/pe/rich.rs b/vendor/object/src/read/pe/rich.rs deleted file mode 100644 index 33dd039..0000000 --- a/vendor/object/src/read/pe/rich.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! PE rich header handling - -use core::mem; - -use crate::pod::bytes_of_slice; -use crate::read::Bytes; -use crate::{pe, LittleEndian as LE, ReadRef, U32}; - -/// Parsed information about a Rich Header. -#[derive(Debug, Clone, Copy)] -pub struct RichHeaderInfo<'data> { - /// The offset at which the rich header starts. - pub offset: usize, - /// The length (in bytes) of the rich header. - /// - /// This includes the payload, but also the 16-byte start sequence and the - /// 8-byte final "Rich" and XOR key. - pub length: usize, - /// The XOR key used to mask the rich header. - /// - /// Unless the file has been tampered with, it should be equal to a checksum - /// of the file header. - pub xor_key: u32, - masked_entries: &'data [pe::MaskedRichHeaderEntry], -} - -/// A PE rich header entry after it has been unmasked. -/// -/// See [`pe::MaskedRichHeaderEntry`]. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct RichHeaderEntry { - /// ID of the component. - pub comp_id: u32, - /// Number of times this component has been used when building this PE. - pub count: u32, -} - -impl<'data> RichHeaderInfo<'data> { - /// Try to locate a rich header and its entries in the current PE file. - pub fn parse>(data: R, nt_header_offset: u64) -> Option { - // Locate the rich header, if any. - // It ends with the "Rich" string and an XOR key, before the NT header. - let data = data.read_bytes_at(0, nt_header_offset).map(Bytes).ok()?; - let end_marker_offset = memmem(data.0, b"Rich", 4)?; - let xor_key = *data.read_at::>(end_marker_offset + 4).ok()?; - - // It starts at the masked "DanS" string and 3 masked zeroes. - let masked_start_marker = U32::new(LE, 0x536e_6144 ^ xor_key.get(LE)); - let start_header = [masked_start_marker, xor_key, xor_key, xor_key]; - let start_sequence = bytes_of_slice(&start_header); - let start_marker_offset = memmem(&data.0[..end_marker_offset], start_sequence, 4)?; - - // Extract the items between the markers. - let items_offset = start_marker_offset + start_sequence.len(); - let items_len = end_marker_offset - items_offset; - let item_count = items_len / mem::size_of::(); - let items = data.read_slice_at(items_offset, item_count).ok()?; - Some(RichHeaderInfo { - offset: start_marker_offset, - // Includes "Rich" marker and the XOR key. - length: end_marker_offset - start_marker_offset + 8, - xor_key: xor_key.get(LE), - masked_entries: items, - }) - } - - /// Returns an iterator over the unmasked entries. - pub fn unmasked_entries(&self) -> impl Iterator + 'data { - let xor_key = self.xor_key; - self.masked_entries - .iter() - .map(move |entry| RichHeaderEntry { - comp_id: entry.masked_comp_id.get(LE) ^ xor_key, - count: entry.masked_count.get(LE) ^ xor_key, - }) - } -} - -/// Find the offset of the first occurrence of needle in the data. -/// -/// The offset must have the given alignment. -fn memmem(data: &[u8], needle: &[u8], align: usize) -> Option { - let mut offset = 0; - loop { - if data.get(offset..)?.get(..needle.len())? == needle { - return Some(offset); - } - offset += align; - } -} diff --git a/vendor/object/src/read/pe/section.rs b/vendor/object/src/read/pe/section.rs deleted file mode 100644 index 74c9d7f..0000000 --- a/vendor/object/src/read/pe/section.rs +++ /dev/null @@ -1,440 +0,0 @@ -use core::marker::PhantomData; -use core::{cmp, iter, slice, str}; - -use crate::endian::LittleEndian as LE; -use crate::pe; -use crate::pe::ImageSectionHeader; -use crate::read::{ - self, CompressedData, CompressedFileRange, ObjectSection, ObjectSegment, ReadError, ReadRef, - Relocation, Result, SectionFlags, SectionIndex, SectionKind, SegmentFlags, -}; - -use super::{ImageNtHeaders, PeFile, SectionTable}; - -/// An iterator for the loadable sections in a [`PeFile32`](super::PeFile32). -pub type PeSegmentIterator32<'data, 'file, R = &'data [u8]> = - PeSegmentIterator<'data, 'file, pe::ImageNtHeaders32, R>; -/// An iterator for the loadable sections in a [`PeFile64`](super::PeFile64). -pub type PeSegmentIterator64<'data, 'file, R = &'data [u8]> = - PeSegmentIterator<'data, 'file, pe::ImageNtHeaders64, R>; - -/// An iterator for the loadable sections in a [`PeFile`]. -#[derive(Debug)] -pub struct PeSegmentIterator<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - pub(super) file: &'file PeFile<'data, Pe, R>, - pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>, -} - -impl<'data, 'file, Pe, R> Iterator for PeSegmentIterator<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type Item = PeSegment<'data, 'file, Pe, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|section| PeSegment { - file: self.file, - section, - }) - } -} - -/// A loadable section in a [`PeFile32`](super::PeFile32). -pub type PeSegment32<'data, 'file, R = &'data [u8]> = - PeSegment<'data, 'file, pe::ImageNtHeaders32, R>; -/// A loadable section in a [`PeFile64`](super::PeFile64). -pub type PeSegment64<'data, 'file, R = &'data [u8]> = - PeSegment<'data, 'file, pe::ImageNtHeaders64, R>; - -/// A loadable section in a [`PeFile`]. -/// -/// Most functionality is provided by the [`ObjectSegment`] trait implementation. -#[derive(Debug)] -pub struct PeSegment<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - file: &'file PeFile<'data, Pe, R>, - section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, Pe, R> read::private::Sealed for PeSegment<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Pe, R> ObjectSegment<'data> for PeSegment<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base) - } - - #[inline] - fn size(&self) -> u64 { - u64::from(self.section.virtual_size.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.file.section_alignment() - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - let (offset, size) = self.section.pe_file_range(); - (u64::from(offset), u64::from(size)) - } - - fn data(&self) -> Result<&'data [u8]> { - self.section.pe_data(self.file.data) - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.data()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn name_bytes(&self) -> Result> { - self.section - .name(self.file.common.symbols.strings()) - .map(Some) - } - - #[inline] - fn name(&self) -> Result> { - let name = self.section.name(self.file.common.symbols.strings())?; - Ok(Some( - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 PE section name")?, - )) - } - - #[inline] - fn flags(&self) -> SegmentFlags { - let characteristics = self.section.characteristics.get(LE); - SegmentFlags::Coff { characteristics } - } -} - -/// An iterator for the sections in a [`PeFile32`](super::PeFile32). -pub type PeSectionIterator32<'data, 'file, R = &'data [u8]> = - PeSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>; -/// An iterator for the sections in a [`PeFile64`](super::PeFile64). -pub type PeSectionIterator64<'data, 'file, R = &'data [u8]> = - PeSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>; - -/// An iterator for the sections in a [`PeFile`]. -#[derive(Debug)] -pub struct PeSectionIterator<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - pub(super) file: &'file PeFile<'data, Pe, R>, - pub(super) iter: iter::Enumerate>, -} - -impl<'data, 'file, Pe, R> Iterator for PeSectionIterator<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type Item = PeSection<'data, 'file, Pe, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|(index, section)| PeSection { - file: self.file, - index: SectionIndex(index + 1), - section, - }) - } -} - -/// A section in a [`PeFile32`](super::PeFile32). -pub type PeSection32<'data, 'file, R = &'data [u8]> = - PeSection<'data, 'file, pe::ImageNtHeaders32, R>; -/// A section in a [`PeFile64`](super::PeFile64). -pub type PeSection64<'data, 'file, R = &'data [u8]> = - PeSection<'data, 'file, pe::ImageNtHeaders64, R>; - -/// A section in a [`PeFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct PeSection<'data, 'file, Pe, R = &'data [u8]> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - pub(super) file: &'file PeFile<'data, Pe, R>, - pub(super) index: SectionIndex, - pub(super) section: &'data pe::ImageSectionHeader, -} - -impl<'data, 'file, Pe, R> read::private::Sealed for PeSection<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Pe, R> ObjectSection<'data> for PeSection<'data, 'file, Pe, R> -where - Pe: ImageNtHeaders, - R: ReadRef<'data>, -{ - type RelocationIterator = PeRelocationIterator<'data, 'file, R>; - - #[inline] - fn index(&self) -> SectionIndex { - self.index - } - - #[inline] - fn address(&self) -> u64 { - u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base) - } - - #[inline] - fn size(&self) -> u64 { - u64::from(self.section.virtual_size.get(LE)) - } - - #[inline] - fn align(&self) -> u64 { - self.file.section_alignment() - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - let (offset, size) = self.section.pe_file_range(); - if size == 0 { - None - } else { - Some((u64::from(offset), u64::from(size))) - } - } - - fn data(&self) -> Result<&'data [u8]> { - self.section.pe_data(self.file.data) - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.data()?, - self.address(), - address, - size, - )) - } - - #[inline] - fn compressed_file_range(&self) -> Result { - Ok(CompressedFileRange::none(self.file_range())) - } - - #[inline] - fn compressed_data(&self) -> Result> { - self.data().map(CompressedData::none) - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - self.section.name(self.file.common.symbols.strings()) - } - - #[inline] - fn name(&self) -> Result<&str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 PE section name") - } - - #[inline] - fn segment_name_bytes(&self) -> Result> { - Ok(None) - } - - #[inline] - fn segment_name(&self) -> Result> { - Ok(None) - } - - #[inline] - fn kind(&self) -> SectionKind { - self.section.kind() - } - - fn relocations(&self) -> PeRelocationIterator<'data, 'file, R> { - PeRelocationIterator(PhantomData) - } - - fn flags(&self) -> SectionFlags { - SectionFlags::Coff { - characteristics: self.section.characteristics.get(LE), - } - } -} - -impl<'data> SectionTable<'data> { - /// Return the file offset of the given virtual address, and the size up - /// to the end of the section containing it. - /// - /// Returns `None` if no section contains the address. - pub fn pe_file_range_at(&self, va: u32) -> Option<(u32, u32)> { - self.iter().find_map(|section| section.pe_file_range_at(va)) - } - - /// Return the data starting at the given virtual address, up to the end of the - /// section containing it. - /// - /// Ignores sections with invalid data. - /// - /// Returns `None` if no section contains the address. - pub fn pe_data_at>(&self, data: R, va: u32) -> Option<&'data [u8]> { - self.iter().find_map(|section| section.pe_data_at(data, va)) - } - - /// Return the data of the section that contains the given virtual address in a PE file. - /// - /// Also returns the virtual address of that section. - /// - /// Ignores sections with invalid data. - pub fn pe_data_containing>( - &self, - data: R, - va: u32, - ) -> Option<(&'data [u8], u32)> { - self.iter() - .find_map(|section| section.pe_data_containing(data, va)) - } - - /// Return the section that contains a given virtual address. - pub fn section_containing(&self, va: u32) -> Option<&'data ImageSectionHeader> { - self.iter().find(|section| section.contains_rva(va)) - } -} - -impl pe::ImageSectionHeader { - /// Return the offset and size of the section in a PE file. - /// - /// The size of the range will be the minimum of the file size and virtual size. - pub fn pe_file_range(&self) -> (u32, u32) { - // Pointer and size will be zero for uninitialized data; we don't need to validate this. - let offset = self.pointer_to_raw_data.get(LE); - let size = cmp::min(self.virtual_size.get(LE), self.size_of_raw_data.get(LE)); - (offset, size) - } - - /// Return the file offset of the given virtual address, and the remaining size up - /// to the end of the section. - /// - /// Returns `None` if the section does not contain the address. - pub fn pe_file_range_at(&self, va: u32) -> Option<(u32, u32)> { - let section_va = self.virtual_address.get(LE); - let offset = va.checked_sub(section_va)?; - let (section_offset, section_size) = self.pe_file_range(); - // Address must be within section (and not at its end). - if offset < section_size { - Some((section_offset.checked_add(offset)?, section_size - offset)) - } else { - None - } - } - - /// Return the virtual address and size of the section. - pub fn pe_address_range(&self) -> (u32, u32) { - (self.virtual_address.get(LE), self.virtual_size.get(LE)) - } - - /// Return the section data in a PE file. - /// - /// The length of the data will be the minimum of the file size and virtual size. - pub fn pe_data<'data, R: ReadRef<'data>>(&self, data: R) -> Result<&'data [u8]> { - let (offset, size) = self.pe_file_range(); - data.read_bytes_at(offset.into(), size.into()) - .read_error("Invalid PE section offset or size") - } - - /// Return the data starting at the given virtual address, up to the end of the - /// section. - /// - /// Ignores sections with invalid data. - /// - /// Returns `None` if the section does not contain the address. - pub fn pe_data_at<'data, R: ReadRef<'data>>(&self, data: R, va: u32) -> Option<&'data [u8]> { - let (offset, size) = self.pe_file_range_at(va)?; - data.read_bytes_at(offset.into(), size.into()).ok() - } - - /// Tests whether a given RVA is part of this section - pub fn contains_rva(&self, va: u32) -> bool { - let section_va = self.virtual_address.get(LE); - match va.checked_sub(section_va) { - None => false, - Some(offset) => { - // Address must be within section (and not at its end). - offset < self.virtual_size.get(LE) - } - } - } - - /// Return the section data if it contains the given virtual address. - /// - /// Also returns the virtual address of that section. - /// - /// Ignores sections with invalid data. - pub fn pe_data_containing<'data, R: ReadRef<'data>>( - &self, - data: R, - va: u32, - ) -> Option<(&'data [u8], u32)> { - let section_va = self.virtual_address.get(LE); - let offset = va.checked_sub(section_va)?; - let (section_offset, section_size) = self.pe_file_range(); - // Address must be within section (and not at its end). - if offset < section_size { - let section_data = data - .read_bytes_at(section_offset.into(), section_size.into()) - .ok()?; - Some((section_data, section_va)) - } else { - None - } - } -} - -/// An iterator for the relocations in an [`PeSection`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct PeRelocationIterator<'data, 'file, R = &'data [u8]>( - PhantomData<(&'data (), &'file (), R)>, -); - -impl<'data, 'file, R> Iterator for PeRelocationIterator<'data, 'file, R> { - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - None - } -} diff --git a/vendor/object/src/read/read_cache.rs b/vendor/object/src/read/read_cache.rs deleted file mode 100644 index d1377f1..0000000 --- a/vendor/object/src/read/read_cache.rs +++ /dev/null @@ -1,178 +0,0 @@ -use core::ops::Range; -use std::boxed::Box; -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::HashMap; -use std::convert::TryInto; -use std::io::{Read, Seek, SeekFrom}; -use std::mem; -use std::vec::Vec; - -use crate::read::ReadRef; - -/// An implementation of [`ReadRef`] for data in a stream that implements -/// `Read + Seek`. -/// -/// Contains a cache of read-only blocks of data, allowing references to -/// them to be returned. Entries in the cache are never removed. -/// Entries are keyed on the offset and size of the read. -/// Currently overlapping reads are considered separate reads. -#[derive(Debug)] -pub struct ReadCache { - cache: RefCell>, -} - -#[derive(Debug)] -struct ReadCacheInternal { - read: R, - bufs: HashMap<(u64, u64), Box<[u8]>>, - strings: HashMap<(u64, u8), Box<[u8]>>, -} - -impl ReadCache { - /// Create an empty `ReadCache` for the given stream. - pub fn new(read: R) -> Self { - ReadCache { - cache: RefCell::new(ReadCacheInternal { - read, - bufs: HashMap::new(), - strings: HashMap::new(), - }), - } - } - - /// Return an implementation of `ReadRef` that restricts reads - /// to the given range of the stream. - pub fn range(&self, offset: u64, size: u64) -> ReadCacheRange<'_, R> { - ReadCacheRange { - r: self, - offset, - size, - } - } - - /// Free buffers used by the cache. - pub fn clear(&mut self) { - self.cache.borrow_mut().bufs.clear(); - } - - /// Unwrap this `ReadCache`, returning the underlying reader. - pub fn into_inner(self) -> R { - self.cache.into_inner().read - } -} - -impl<'a, R: Read + Seek> ReadRef<'a> for &'a ReadCache { - fn len(self) -> Result { - let cache = &mut *self.cache.borrow_mut(); - cache.read.seek(SeekFrom::End(0)).map_err(|_| ()) - } - - fn read_bytes_at(self, offset: u64, size: u64) -> Result<&'a [u8], ()> { - if size == 0 { - return Ok(&[]); - } - let cache = &mut *self.cache.borrow_mut(); - let buf = match cache.bufs.entry((offset, size)) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => { - let size = size.try_into().map_err(|_| ())?; - cache.read.seek(SeekFrom::Start(offset)).map_err(|_| ())?; - let mut bytes = vec![0; size].into_boxed_slice(); - cache.read.read_exact(&mut bytes).map_err(|_| ())?; - entry.insert(bytes) - } - }; - // Extend the lifetime to that of self. - // This is OK because we never mutate or remove entries. - Ok(unsafe { mem::transmute::<&[u8], &[u8]>(buf) }) - } - - fn read_bytes_at_until(self, range: Range, delimiter: u8) -> Result<&'a [u8], ()> { - let cache = &mut *self.cache.borrow_mut(); - let buf = match cache.strings.entry((range.start, delimiter)) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => { - cache - .read - .seek(SeekFrom::Start(range.start)) - .map_err(|_| ())?; - - let max_check: usize = (range.end - range.start).try_into().map_err(|_| ())?; - // Strings should be relatively small. - // TODO: make this configurable? - let max_check = max_check.min(4096); - - let mut bytes = Vec::new(); - let mut checked = 0; - loop { - bytes.resize((checked + 256).min(max_check), 0); - let read = cache.read.read(&mut bytes[checked..]).map_err(|_| ())?; - if read == 0 { - return Err(()); - } - if let Some(len) = memchr::memchr(delimiter, &bytes[checked..][..read]) { - bytes.truncate(checked + len); - break entry.insert(bytes.into_boxed_slice()); - } - checked += read; - if checked >= max_check { - return Err(()); - } - } - } - }; - // Extend the lifetime to that of self. - // This is OK because we never mutate or remove entries. - Ok(unsafe { mem::transmute::<&[u8], &[u8]>(buf) }) - } -} - -/// An implementation of [`ReadRef`] for a range of data in a stream that -/// implements `Read + Seek`. -/// -/// Shares an underlying `ReadCache` with a lifetime of `'a`. -#[derive(Debug)] -pub struct ReadCacheRange<'a, R: Read + Seek> { - r: &'a ReadCache, - offset: u64, - size: u64, -} - -impl<'a, R: Read + Seek> Clone for ReadCacheRange<'a, R> { - fn clone(&self) -> Self { - *self - } -} - -impl<'a, R: Read + Seek> Copy for ReadCacheRange<'a, R> {} - -impl<'a, R: Read + Seek> ReadRef<'a> for ReadCacheRange<'a, R> { - fn len(self) -> Result { - Ok(self.size) - } - - fn read_bytes_at(self, offset: u64, size: u64) -> Result<&'a [u8], ()> { - if size == 0 { - return Ok(&[]); - } - let end = offset.checked_add(size).ok_or(())?; - if end > self.size { - return Err(()); - } - let r_offset = self.offset.checked_add(offset).ok_or(())?; - self.r.read_bytes_at(r_offset, size) - } - - fn read_bytes_at_until(self, range: Range, delimiter: u8) -> Result<&'a [u8], ()> { - let r_start = self.offset.checked_add(range.start).ok_or(())?; - let r_end = self.offset.checked_add(range.end).ok_or(())?; - let bytes = self.r.read_bytes_at_until(r_start..r_end, delimiter)?; - let size = bytes.len().try_into().map_err(|_| ())?; - let end = range.start.checked_add(size).ok_or(())?; - if end > self.size { - return Err(()); - } - Ok(bytes) - } -} diff --git a/vendor/object/src/read/read_ref.rs b/vendor/object/src/read/read_ref.rs deleted file mode 100644 index 8b87cba..0000000 --- a/vendor/object/src/read/read_ref.rs +++ /dev/null @@ -1,137 +0,0 @@ -#![allow(clippy::len_without_is_empty)] - -use core::convert::TryInto; -use core::ops::Range; -use core::{mem, result}; - -use crate::pod::{from_bytes, slice_from_bytes, Pod}; - -type Result = result::Result; - -/// A trait for reading references to [`Pod`] types from a block of data. -/// -/// This allows parsers to handle both of these cases: -/// - the block of data exists in memory, and it is desirable -/// to use references to this block instead of copying it, -/// - the block of data exists in storage, and it is desirable -/// to read on demand to minimize I/O and memory usage. -/// -/// The methods accept `self` by value because `Self` is expected to behave -/// similar to a reference: it may be a reference with a lifetime of `'a`, -/// or it may be a wrapper of a reference. -/// -/// The `Clone` and `Copy` bounds are for convenience, and since `Self` is -/// expected to be similar to a reference, these are easily satisfied. -/// -/// Object file parsers typically use offsets to locate the structures -/// in the block, and will most commonly use the `*_at` methods to -/// read a structure at a known offset. -/// -/// Occasionally file parsers will need to treat the block as a stream, -/// and so convenience methods are provided that update an offset with -/// the size that was read. -// -// An alternative would be for methods to accept `&mut self` and use a -// `seek` method instead of the `offset` parameters, but this is less -// convenient for implementers. -pub trait ReadRef<'a>: Clone + Copy { - /// The total size of the block of data. - fn len(self) -> Result; - - /// Get a reference to a `u8` slice at the given offset. - /// - /// Returns an error if offset or size are out of bounds. - fn read_bytes_at(self, offset: u64, size: u64) -> Result<&'a [u8]>; - - /// Get a reference to a delimited `u8` slice which starts at range.start. - /// - /// Does not include the delimiter. - /// - /// Returns an error if the range is out of bounds or the delimiter is - /// not found in the range. - fn read_bytes_at_until(self, range: Range, delimiter: u8) -> Result<&'a [u8]>; - - /// Get a reference to a `u8` slice at the given offset, and update the offset. - /// - /// Returns an error if offset or size are out of bounds. - fn read_bytes(self, offset: &mut u64, size: u64) -> Result<&'a [u8]> { - let bytes = self.read_bytes_at(*offset, size)?; - *offset = offset.wrapping_add(size); - Ok(bytes) - } - - /// Get a reference to a `Pod` type at the given offset, and update the offset. - /// - /// Returns an error if offset or size are out of bounds. - /// - /// The default implementation uses `read_bytes`, and returns an error if - /// `read_bytes` does not return bytes with the correct alignment for `T`. - /// Implementors may want to provide their own implementation that ensures - /// the alignment can be satisfied. Alternatively, only use this method with - /// types that do not need alignment (see the `unaligned` feature of this crate). - fn read(self, offset: &mut u64) -> Result<&'a T> { - let size = mem::size_of::().try_into().map_err(|_| ())?; - let bytes = self.read_bytes(offset, size)?; - let (t, _) = from_bytes(bytes)?; - Ok(t) - } - - /// Get a reference to a `Pod` type at the given offset. - /// - /// Returns an error if offset or size are out of bounds. - /// - /// Also see the `read` method for information regarding alignment of `T`. - fn read_at(self, mut offset: u64) -> Result<&'a T> { - self.read(&mut offset) - } - - /// Get a reference to a slice of a `Pod` type at the given offset, and update the offset. - /// - /// Returns an error if offset or size are out of bounds. - /// - /// Also see the `read` method for information regarding alignment of `T`. - fn read_slice(self, offset: &mut u64, count: usize) -> Result<&'a [T]> { - let size = count - .checked_mul(mem::size_of::()) - .ok_or(())? - .try_into() - .map_err(|_| ())?; - let bytes = self.read_bytes(offset, size)?; - let (t, _) = slice_from_bytes(bytes, count)?; - Ok(t) - } - - /// Get a reference to a slice of a `Pod` type at the given offset. - /// - /// Returns an error if offset or size are out of bounds. - /// - /// Also see the `read` method for information regarding alignment of `T`. - fn read_slice_at(self, mut offset: u64, count: usize) -> Result<&'a [T]> { - self.read_slice(&mut offset, count) - } -} - -impl<'a> ReadRef<'a> for &'a [u8] { - fn len(self) -> Result { - self.len().try_into().map_err(|_| ()) - } - - fn read_bytes_at(self, offset: u64, size: u64) -> Result<&'a [u8]> { - let offset: usize = offset.try_into().map_err(|_| ())?; - let size: usize = size.try_into().map_err(|_| ())?; - self.get(offset..).ok_or(())?.get(..size).ok_or(()) - } - - fn read_bytes_at_until(self, range: Range, delimiter: u8) -> Result<&'a [u8]> { - let start: usize = range.start.try_into().map_err(|_| ())?; - let end: usize = range.end.try_into().map_err(|_| ())?; - let bytes = self.get(start..end).ok_or(())?; - match memchr::memchr(delimiter, bytes) { - Some(len) => { - // This will never fail. - bytes.get(..len).ok_or(()) - } - None => Err(()), - } - } -} diff --git a/vendor/object/src/read/traits.rs b/vendor/object/src/read/traits.rs deleted file mode 100644 index 67105d3..0000000 --- a/vendor/object/src/read/traits.rs +++ /dev/null @@ -1,551 +0,0 @@ -use alloc::borrow::Cow; -use alloc::vec::Vec; - -use crate::read::{ - self, Architecture, CodeView, ComdatKind, CompressedData, CompressedFileRange, Export, - FileFlags, Import, ObjectKind, ObjectMap, Relocation, Result, SectionFlags, SectionIndex, - SectionKind, SegmentFlags, SubArchitecture, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, - SymbolMapName, SymbolScope, SymbolSection, -}; -use crate::Endianness; - -/// An object file. -/// -/// This is the primary trait for the unified read API. -pub trait Object<'data: 'file, 'file>: read::private::Sealed { - /// A loadable segment in the object file. - type Segment: ObjectSegment<'data>; - - /// An iterator for the loadable segments in the object file. - type SegmentIterator: Iterator; - - /// A section in the object file. - type Section: ObjectSection<'data>; - - /// An iterator for the sections in the object file. - type SectionIterator: Iterator; - - /// A COMDAT section group in the object file. - type Comdat: ObjectComdat<'data>; - - /// An iterator for the COMDAT section groups in the object file. - type ComdatIterator: Iterator; - - /// A symbol in the object file. - type Symbol: ObjectSymbol<'data>; - - /// An iterator for symbols in the object file. - type SymbolIterator: Iterator; - - /// A symbol table in the object file. - type SymbolTable: ObjectSymbolTable< - 'data, - Symbol = Self::Symbol, - SymbolIterator = Self::SymbolIterator, - >; - - /// An iterator for the dynamic relocations in the file. - /// - /// The first field in the item tuple is the address - /// that the relocation applies to. - type DynamicRelocationIterator: Iterator; - - /// Get the architecture type of the file. - fn architecture(&self) -> Architecture; - - /// Get the sub-architecture type of the file if known. - /// - /// A value of `None` has a range of meanings: the file supports all - /// sub-architectures, the file does not explicitly specify a - /// sub-architecture, or the sub-architecture is currently unrecognized. - fn sub_architecture(&self) -> Option { - None - } - - /// Get the endianness of the file. - #[inline] - fn endianness(&self) -> Endianness { - if self.is_little_endian() { - Endianness::Little - } else { - Endianness::Big - } - } - - /// Return true if the file is little endian, false if it is big endian. - fn is_little_endian(&self) -> bool; - - /// Return true if the file can contain 64-bit addresses. - fn is_64(&self) -> bool; - - /// Return the kind of this object. - fn kind(&self) -> ObjectKind; - - /// Get an iterator for the loadable segments in the file. - /// - /// For ELF, this is program headers with type [`PT_LOAD`](crate::elf::PT_LOAD). - /// For Mach-O, this is load commands with type [`LC_SEGMENT`](crate::macho::LC_SEGMENT) - /// or [`LC_SEGMENT_64`](crate::macho::LC_SEGMENT_64). - /// For PE, this is all sections. - fn segments(&'file self) -> Self::SegmentIterator; - - /// Get the section named `section_name`, if such a section exists. - /// - /// If `section_name` starts with a '.' then it is treated as a system section name, - /// and is compared using the conventions specific to the object file format. This - /// includes: - /// - if ".debug_str_offsets" is requested for a Mach-O object file, then the actual - /// section name that is searched for is "__debug_str_offs". - /// - if ".debug_info" is requested for an ELF object file, then - /// ".zdebug_info" may be returned (and similarly for other debug sections). - /// - /// For some object files, multiple segments may contain sections with the same - /// name. In this case, the first matching section will be used. - /// - /// This method skips over sections with invalid names. - fn section_by_name(&'file self, section_name: &str) -> Option { - self.section_by_name_bytes(section_name.as_bytes()) - } - - /// Like [`Self::section_by_name`], but allows names that are not UTF-8. - fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option; - - /// Get the section at the given index. - /// - /// The meaning of the index depends on the object file. - /// - /// For some object files, this requires iterating through all sections. - /// - /// Returns an error if the index is invalid. - fn section_by_index(&'file self, index: SectionIndex) -> Result; - - /// Get an iterator for the sections in the file. - fn sections(&'file self) -> Self::SectionIterator; - - /// Get an iterator for the COMDAT section groups in the file. - fn comdats(&'file self) -> Self::ComdatIterator; - - /// Get the debugging symbol table, if any. - fn symbol_table(&'file self) -> Option; - - /// Get the debugging symbol at the given index. - /// - /// The meaning of the index depends on the object file. - /// - /// Returns an error if the index is invalid. - fn symbol_by_index(&'file self, index: SymbolIndex) -> Result; - - /// Get an iterator for the debugging symbols in the file. - /// - /// This may skip over symbols that are malformed or unsupported. - /// - /// For Mach-O files, this does not include STAB entries. - fn symbols(&'file self) -> Self::SymbolIterator; - - /// Get the symbol named `symbol_name`, if the symbol exists. - fn symbol_by_name(&'file self, symbol_name: &str) -> Option { - self.symbol_by_name_bytes(symbol_name.as_bytes()) - } - - /// Like [`Self::symbol_by_name`], but allows names that are not UTF-8. - fn symbol_by_name_bytes(&'file self, symbol_name: &[u8]) -> Option { - self.symbols() - .find(|sym| sym.name_bytes() == Ok(symbol_name)) - } - - /// Get the dynamic linking symbol table, if any. - /// - /// Only ELF has a separate dynamic linking symbol table. - /// Consider using [`Self::exports`] or [`Self::imports`] instead. - fn dynamic_symbol_table(&'file self) -> Option; - - /// Get an iterator for the dynamic linking symbols in the file. - /// - /// This may skip over symbols that are malformed or unsupported. - /// - /// Only ELF has dynamic linking symbols. - /// Other file formats will return an empty iterator. - /// Consider using [`Self::exports`] or [`Self::imports`] instead. - fn dynamic_symbols(&'file self) -> Self::SymbolIterator; - - /// Get the dynamic relocations for this file. - /// - /// Symbol indices in these relocations refer to the dynamic symbol table. - /// - /// Only ELF has dynamic relocations. - fn dynamic_relocations(&'file self) -> Option; - - /// Construct a map from addresses to symbol names. - /// - /// The map will only contain defined text and data symbols. - /// The dynamic symbol table will only be used if there are no debugging symbols. - fn symbol_map(&'file self) -> SymbolMap> { - let mut symbols = Vec::new(); - if let Some(table) = self.symbol_table().or_else(|| self.dynamic_symbol_table()) { - // Sometimes symbols share addresses. Collect them all then choose the "best". - let mut all_symbols = Vec::new(); - for symbol in table.symbols() { - // Must have an address. - if !symbol.is_definition() { - continue; - } - // Must have a name. - let name = match symbol.name() { - Ok(name) => name, - _ => continue, - }; - if name.is_empty() { - continue; - } - - // Lower is better. - let mut priority = 0u32; - - // Prefer known kind. - match symbol.kind() { - SymbolKind::Text | SymbolKind::Data => {} - SymbolKind::Unknown => priority += 1, - _ => continue, - } - priority *= 2; - - // Prefer global visibility. - priority += match symbol.scope() { - SymbolScope::Unknown => 3, - SymbolScope::Compilation => 2, - SymbolScope::Linkage => 1, - SymbolScope::Dynamic => 0, - }; - priority *= 4; - - // Prefer later entries (earlier symbol is likely to be less specific). - let index = !0 - symbol.index().0; - - // Tuple is ordered for sort. - all_symbols.push((symbol.address(), priority, index, name)); - } - // Unstable sort is okay because tuple includes index. - all_symbols.sort_unstable(); - - let mut previous_address = !0; - for (address, _priority, _index, name) in all_symbols { - if address != previous_address { - symbols.push(SymbolMapName::new(address, name)); - previous_address = address; - } - } - } - SymbolMap::new(symbols) - } - - /// Construct a map from addresses to symbol names and object file names. - /// - /// This is derived from Mach-O STAB entries. - fn object_map(&'file self) -> ObjectMap<'data> { - ObjectMap::default() - } - - /// Get the imported symbols. - fn imports(&self) -> Result>>; - - /// Get the exported symbols that expose both a name and an address. - /// - /// Some file formats may provide other kinds of symbols that can be retrieved using - /// the low level API. - fn exports(&self) -> Result>>; - - /// Return true if the file contains DWARF debug information sections, false if not. - fn has_debug_symbols(&self) -> bool; - - /// The UUID from a Mach-O [`LC_UUID`](crate::macho::LC_UUID) load command. - #[inline] - fn mach_uuid(&self) -> Result> { - Ok(None) - } - - /// The build ID from an ELF [`NT_GNU_BUILD_ID`](crate::elf::NT_GNU_BUILD_ID) note. - #[inline] - fn build_id(&self) -> Result> { - Ok(None) - } - - /// The filename and CRC from a `.gnu_debuglink` section. - #[inline] - fn gnu_debuglink(&self) -> Result> { - Ok(None) - } - - /// The filename and build ID from a `.gnu_debugaltlink` section. - #[inline] - fn gnu_debugaltlink(&self) -> Result> { - Ok(None) - } - - /// The filename and GUID from the PE CodeView section. - #[inline] - fn pdb_info(&self) -> Result>> { - Ok(None) - } - - /// Get the base address used for relative virtual addresses. - /// - /// Currently this is only non-zero for PE. - fn relative_address_base(&'file self) -> u64; - - /// Get the virtual address of the entry point of the binary. - fn entry(&'file self) -> u64; - - /// File flags that are specific to each file format. - fn flags(&self) -> FileFlags; -} - -/// A loadable segment in an [`Object`]. -/// -/// This trait is part of the unified read API. -pub trait ObjectSegment<'data>: read::private::Sealed { - /// Returns the virtual address of the segment. - fn address(&self) -> u64; - - /// Returns the size of the segment in memory. - fn size(&self) -> u64; - - /// Returns the alignment of the segment in memory. - fn align(&self) -> u64; - - /// Returns the offset and size of the segment in the file. - fn file_range(&self) -> (u64, u64); - - /// Returns a reference to the file contents of the segment. - /// - /// The length of this data may be different from the size of the - /// segment in memory. - fn data(&self) -> Result<&'data [u8]>; - - /// Return the segment data in the given range. - /// - /// Returns `Ok(None)` if the segment does not contain the given range. - fn data_range(&self, address: u64, size: u64) -> Result>; - - /// Returns the name of the segment. - fn name_bytes(&self) -> Result>; - - /// Returns the name of the segment. - /// - /// Returns an error if the name is not UTF-8. - fn name(&self) -> Result>; - - /// Return the flags of segment. - fn flags(&self) -> SegmentFlags; -} - -/// A section in an [`Object`]. -/// -/// This trait is part of the unified read API. -pub trait ObjectSection<'data>: read::private::Sealed { - /// An iterator for the relocations for a section. - /// - /// The first field in the item tuple is the section offset - /// that the relocation applies to. - type RelocationIterator: Iterator; - - /// Returns the section index. - fn index(&self) -> SectionIndex; - - /// Returns the address of the section. - fn address(&self) -> u64; - - /// Returns the size of the section in memory. - fn size(&self) -> u64; - - /// Returns the alignment of the section in memory. - fn align(&self) -> u64; - - /// Returns offset and size of on-disk segment (if any). - fn file_range(&self) -> Option<(u64, u64)>; - - /// Returns the raw contents of the section. - /// - /// The length of this data may be different from the size of the - /// section in memory. - /// - /// This does not do any decompression. - fn data(&self) -> Result<&'data [u8]>; - - /// Return the raw contents of the section data in the given range. - /// - /// This does not do any decompression. - /// - /// Returns `Ok(None)` if the section does not contain the given range. - fn data_range(&self, address: u64, size: u64) -> Result>; - - /// Returns the potentially compressed file range of the section, - /// along with information about the compression. - fn compressed_file_range(&self) -> Result; - - /// Returns the potentially compressed contents of the section, - /// along with information about the compression. - fn compressed_data(&self) -> Result>; - - /// Returns the uncompressed contents of the section. - /// - /// The length of this data may be different from the size of the - /// section in memory. - /// - /// If no compression is detected, then returns the data unchanged. - /// Returns `Err` if decompression fails. - fn uncompressed_data(&self) -> Result> { - self.compressed_data()?.decompress() - } - - /// Returns the name of the section. - fn name_bytes(&self) -> Result<&[u8]>; - - /// Returns the name of the section. - /// - /// Returns an error if the name is not UTF-8. - fn name(&self) -> Result<&str>; - - /// Returns the name of the segment for this section. - fn segment_name_bytes(&self) -> Result>; - - /// Returns the name of the segment for this section. - /// - /// Returns an error if the name is not UTF-8. - fn segment_name(&self) -> Result>; - - /// Return the kind of this section. - fn kind(&self) -> SectionKind; - - /// Get the relocations for this section. - fn relocations(&self) -> Self::RelocationIterator; - - /// Section flags that are specific to each file format. - fn flags(&self) -> SectionFlags; -} - -/// A COMDAT section group in an [`Object`]. -/// -/// This trait is part of the unified read API. -pub trait ObjectComdat<'data>: read::private::Sealed { - /// An iterator for the sections in the section group. - type SectionIterator: Iterator; - - /// Returns the COMDAT selection kind. - fn kind(&self) -> ComdatKind; - - /// Returns the index of the symbol used for the name of COMDAT section group. - fn symbol(&self) -> SymbolIndex; - - /// Returns the name of the COMDAT section group. - fn name_bytes(&self) -> Result<&[u8]>; - - /// Returns the name of the COMDAT section group. - /// - /// Returns an error if the name is not UTF-8. - fn name(&self) -> Result<&str>; - - /// Get the sections in this section group. - fn sections(&self) -> Self::SectionIterator; -} - -/// A symbol table in an [`Object`]. -/// -/// This trait is part of the unified read API. -pub trait ObjectSymbolTable<'data>: read::private::Sealed { - /// A symbol table entry. - type Symbol: ObjectSymbol<'data>; - - /// An iterator for the symbols in a symbol table. - type SymbolIterator: Iterator; - - /// Get an iterator for the symbols in the table. - /// - /// This may skip over symbols that are malformed or unsupported. - fn symbols(&self) -> Self::SymbolIterator; - - /// Get the symbol at the given index. - /// - /// The meaning of the index depends on the object file. - /// - /// Returns an error if the index is invalid. - fn symbol_by_index(&self, index: SymbolIndex) -> Result; -} - -/// A symbol table entry in an [`Object`]. -/// -/// This trait is part of the unified read API. -pub trait ObjectSymbol<'data>: read::private::Sealed { - /// The index of the symbol. - fn index(&self) -> SymbolIndex; - - /// The name of the symbol. - fn name_bytes(&self) -> Result<&'data [u8]>; - - /// The name of the symbol. - /// - /// Returns an error if the name is not UTF-8. - fn name(&self) -> Result<&'data str>; - - /// The address of the symbol. May be zero if the address is unknown. - fn address(&self) -> u64; - - /// The size of the symbol. May be zero if the size is unknown. - fn size(&self) -> u64; - - /// Return the kind of this symbol. - fn kind(&self) -> SymbolKind; - - /// Returns the section where the symbol is defined. - fn section(&self) -> SymbolSection; - - /// Returns the section index for the section containing this symbol. - /// - /// May return `None` if the symbol is not defined in a section. - fn section_index(&self) -> Option { - self.section().index() - } - - /// Return true if the symbol is undefined. - fn is_undefined(&self) -> bool; - - /// Return true if the symbol is a definition of a function or data object - /// that has a known address. - /// - /// This is primarily used to implement [`Object::symbol_map`]. - fn is_definition(&self) -> bool; - - /// Return true if the symbol is common data. - /// - /// Note: does not check for [`SymbolSection::Section`] with [`SectionKind::Common`]. - fn is_common(&self) -> bool; - - /// Return true if the symbol is weak. - fn is_weak(&self) -> bool; - - /// Returns the symbol scope. - fn scope(&self) -> SymbolScope; - - /// Return true if the symbol visible outside of the compilation unit. - /// - /// This treats [`SymbolScope::Unknown`] as global. - fn is_global(&self) -> bool; - - /// Return true if the symbol is only visible within the compilation unit. - fn is_local(&self) -> bool; - - /// Symbol flags that are specific to each file format. - fn flags(&self) -> SymbolFlags; -} - -/// An iterator for files that don't have dynamic relocations. -#[derive(Debug)] -pub struct NoDynamicRelocationIterator; - -impl Iterator for NoDynamicRelocationIterator { - type Item = (u64, Relocation); - - #[inline] - fn next(&mut self) -> Option { - None - } -} diff --git a/vendor/object/src/read/util.rs b/vendor/object/src/read/util.rs deleted file mode 100644 index 7d85b27..0000000 --- a/vendor/object/src/read/util.rs +++ /dev/null @@ -1,425 +0,0 @@ -use alloc::string::String; -use core::convert::TryInto; -use core::fmt; -use core::marker::PhantomData; - -use crate::pod::{from_bytes, slice_from_bytes, Pod}; -use crate::ReadRef; - -/// A newtype for byte slices. -/// -/// It has these important features: -/// - no methods that can panic, such as `Index` -/// - convenience methods for `Pod` types -/// - a useful `Debug` implementation -#[derive(Default, Clone, Copy, PartialEq, Eq)] -pub struct Bytes<'data>(pub &'data [u8]); - -impl<'data> fmt::Debug for Bytes<'data> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - debug_list_bytes(self.0, fmt) - } -} - -impl<'data> Bytes<'data> { - /// Return the length of the byte slice. - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } - - /// Return true if the byte slice is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Skip over the given number of bytes at the start of the byte slice. - /// - /// Modifies the byte slice to start after the bytes. - /// - /// Returns an error if there are too few bytes. - #[inline] - pub fn skip(&mut self, offset: usize) -> Result<(), ()> { - match self.0.get(offset..) { - Some(tail) => { - self.0 = tail; - Ok(()) - } - None => { - self.0 = &[]; - Err(()) - } - } - } - - /// Return a reference to the given number of bytes at the start of the byte slice. - /// - /// Modifies the byte slice to start after the bytes. - /// - /// Returns an error if there are too few bytes. - #[inline] - pub fn read_bytes(&mut self, count: usize) -> Result, ()> { - match (self.0.get(..count), self.0.get(count..)) { - (Some(head), Some(tail)) => { - self.0 = tail; - Ok(Bytes(head)) - } - _ => { - self.0 = &[]; - Err(()) - } - } - } - - /// Return a reference to the given number of bytes at the given offset of the byte slice. - /// - /// Returns an error if the offset is invalid or there are too few bytes. - #[inline] - pub fn read_bytes_at(mut self, offset: usize, count: usize) -> Result, ()> { - self.skip(offset)?; - self.read_bytes(count) - } - - /// Return a reference to a `Pod` struct at the start of the byte slice. - /// - /// Modifies the byte slice to start after the bytes. - /// - /// Returns an error if there are too few bytes or the slice is incorrectly aligned. - #[inline] - pub fn read(&mut self) -> Result<&'data T, ()> { - match from_bytes(self.0) { - Ok((value, tail)) => { - self.0 = tail; - Ok(value) - } - Err(()) => { - self.0 = &[]; - Err(()) - } - } - } - - /// Return a reference to a `Pod` struct at the given offset of the byte slice. - /// - /// Returns an error if there are too few bytes or the offset is incorrectly aligned. - #[inline] - pub fn read_at(mut self, offset: usize) -> Result<&'data T, ()> { - self.skip(offset)?; - self.read() - } - - /// Return a reference to a slice of `Pod` structs at the start of the byte slice. - /// - /// Modifies the byte slice to start after the bytes. - /// - /// Returns an error if there are too few bytes or the offset is incorrectly aligned. - #[inline] - pub fn read_slice(&mut self, count: usize) -> Result<&'data [T], ()> { - match slice_from_bytes(self.0, count) { - Ok((value, tail)) => { - self.0 = tail; - Ok(value) - } - Err(()) => { - self.0 = &[]; - Err(()) - } - } - } - - /// Return a reference to a slice of `Pod` structs at the given offset of the byte slice. - /// - /// Returns an error if there are too few bytes or the offset is incorrectly aligned. - #[inline] - pub fn read_slice_at(mut self, offset: usize, count: usize) -> Result<&'data [T], ()> { - self.skip(offset)?; - self.read_slice(count) - } - - /// Read a null terminated string. - /// - /// Does not assume any encoding. - /// Reads past the null byte, but doesn't return it. - #[inline] - pub fn read_string(&mut self) -> Result<&'data [u8], ()> { - match memchr::memchr(b'\0', self.0) { - Some(null) => { - // These will never fail. - let bytes = self.read_bytes(null)?; - self.skip(1)?; - Ok(bytes.0) - } - None => { - self.0 = &[]; - Err(()) - } - } - } - - /// Read a null terminated string at an offset. - /// - /// Does not assume any encoding. Does not return the null byte. - #[inline] - pub fn read_string_at(mut self, offset: usize) -> Result<&'data [u8], ()> { - self.skip(offset)?; - self.read_string() - } - - /// Read an unsigned LEB128 number. - pub fn read_uleb128(&mut self) -> Result { - let mut result = 0; - let mut shift = 0; - - loop { - let byte = *self.read::()?; - if shift == 63 && byte != 0x00 && byte != 0x01 { - return Err(()); - } - result |= u64::from(byte & 0x7f) << shift; - shift += 7; - - if byte & 0x80 == 0 { - return Ok(result); - } - } - } - - /// Read a signed LEB128 number. - pub fn read_sleb128(&mut self) -> Result { - let mut result = 0; - let mut shift = 0; - - loop { - let byte = *self.read::()?; - if shift == 63 && byte != 0x00 && byte != 0x7f { - return Err(()); - } - result |= i64::from(byte & 0x7f) << shift; - shift += 7; - - if byte & 0x80 == 0 { - if shift < 64 && (byte & 0x40) != 0 { - // Sign extend the result. - result |= !0 << shift; - } - return Ok(result); - } - } - } -} - -// Only for Debug impl of `Bytes`. -fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut list = fmt.debug_list(); - list.entries(bytes.iter().take(8).copied().map(DebugByte)); - if bytes.len() > 8 { - list.entry(&DebugLen(bytes.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) - } -} - -/// A newtype for byte strings. -/// -/// For byte slices that are strings of an unknown encoding. -/// -/// Provides a `Debug` implementation that interprets the bytes as UTF-8. -#[derive(Default, Clone, Copy, PartialEq, Eq)] -pub(crate) struct ByteString<'data>(pub &'data [u8]); - -impl<'data> fmt::Debug for ByteString<'data> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "\"{}\"", String::from_utf8_lossy(self.0)) - } -} - -#[allow(dead_code)] -#[inline] -pub(crate) fn align(offset: usize, size: usize) -> usize { - (offset + (size - 1)) & !(size - 1) -} - -#[allow(dead_code)] -pub(crate) fn data_range( - data: &[u8], - data_address: u64, - range_address: u64, - size: u64, -) -> Option<&[u8]> { - let offset = range_address.checked_sub(data_address)?; - data.get(offset.try_into().ok()?..)? - .get(..size.try_into().ok()?) -} - -/// A table of zero-terminated strings. -/// -/// This is used by most file formats for strings such as section names and symbol names. -#[derive(Debug, Clone, Copy)] -pub struct StringTable<'data, R = &'data [u8]> -where - R: ReadRef<'data>, -{ - data: Option, - start: u64, - end: u64, - marker: PhantomData<&'data ()>, -} - -impl<'data, R: ReadRef<'data>> StringTable<'data, R> { - /// Interpret the given data as a string table. - pub fn new(data: R, start: u64, end: u64) -> Self { - StringTable { - data: Some(data), - start, - end, - marker: PhantomData, - } - } - - /// Return the string at the given offset. - pub fn get(&self, offset: u32) -> Result<&'data [u8], ()> { - match self.data { - Some(data) => { - let r_start = self.start.checked_add(offset.into()).ok_or(())?; - data.read_bytes_at_until(r_start..self.end, 0) - } - None => Err(()), - } - } -} - -impl<'data, R: ReadRef<'data>> Default for StringTable<'data, R> { - fn default() -> Self { - StringTable { - data: None, - start: 0, - end: 0, - marker: PhantomData, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::pod::bytes_of; - - #[test] - fn bytes() { - let x = u32::to_be(0x0123_4567); - let data = Bytes(bytes_of(&x)); - - let mut bytes = data; - assert_eq!(bytes.skip(0), Ok(())); - assert_eq!(bytes, data); - - let mut bytes = data; - assert_eq!(bytes.skip(4), Ok(())); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.skip(5), Err(())); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.read_bytes(0), Ok(Bytes(&[]))); - assert_eq!(bytes, data); - - let mut bytes = data; - assert_eq!(bytes.read_bytes(4), Ok(data)); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.read_bytes(5), Err(())); - assert_eq!(bytes, Bytes(&[])); - - assert_eq!(data.read_bytes_at(0, 0), Ok(Bytes(&[]))); - assert_eq!(data.read_bytes_at(4, 0), Ok(Bytes(&[]))); - assert_eq!(data.read_bytes_at(0, 4), Ok(data)); - assert_eq!(data.read_bytes_at(1, 4), Err(())); - - let mut bytes = data; - assert_eq!(bytes.read::(), Ok(&u16::to_be(0x0123))); - assert_eq!(bytes, Bytes(&[0x45, 0x67])); - assert_eq!(data.read_at::(2), Ok(&u16::to_be(0x4567))); - assert_eq!(data.read_at::(3), Err(())); - assert_eq!(data.read_at::(4), Err(())); - - let mut bytes = data; - assert_eq!(bytes.read::(), Ok(&x)); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.read::(), Err(())); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.read_slice::(0), Ok(&[][..])); - assert_eq!(bytes, data); - - let mut bytes = data; - assert_eq!(bytes.read_slice::(4), Ok(data.0)); - assert_eq!(bytes, Bytes(&[])); - - let mut bytes = data; - assert_eq!(bytes.read_slice::(5), Err(())); - assert_eq!(bytes, Bytes(&[])); - - assert_eq!(data.read_slice_at::(0, 0), Ok(&[][..])); - assert_eq!(data.read_slice_at::(4, 0), Ok(&[][..])); - assert_eq!(data.read_slice_at::(0, 4), Ok(data.0)); - assert_eq!(data.read_slice_at::(1, 4), Err(())); - - let data = Bytes(&[0x01, 0x02, 0x00, 0x04]); - - let mut bytes = data; - assert_eq!(bytes.read_string(), Ok(&data.0[..2])); - assert_eq!(bytes.0, &data.0[3..]); - - let mut bytes = data; - bytes.skip(3).unwrap(); - assert_eq!(bytes.read_string(), Err(())); - assert_eq!(bytes.0, &[]); - - assert_eq!(data.read_string_at(0), Ok(&data.0[..2])); - assert_eq!(data.read_string_at(1), Ok(&data.0[1..2])); - assert_eq!(data.read_string_at(2), Ok(&[][..])); - assert_eq!(data.read_string_at(3), Err(())); - } - - #[test] - fn bytes_debug() { - assert_eq!(format!("{:?}", Bytes(&[])), "[]"); - assert_eq!(format!("{:?}", Bytes(&[0x01])), "[0x01]"); - assert_eq!( - format!( - "{:?}", - Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]) - ), - "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]" - ); - assert_eq!( - format!( - "{:?}", - Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]) - ), - "[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, ...; 9]" - ); - } -} diff --git a/vendor/object/src/read/wasm.rs b/vendor/object/src/read/wasm.rs deleted file mode 100644 index 4d034bc..0000000 --- a/vendor/object/src/read/wasm.rs +++ /dev/null @@ -1,966 +0,0 @@ -//! Support for reading Wasm files. -//! -//! [`WasmFile`] implements the [`Object`] trait for Wasm files. -use alloc::boxed::Box; -use alloc::vec::Vec; -use core::marker::PhantomData; -use core::ops::Range; -use core::{slice, str}; -use wasmparser as wp; - -use crate::read::{ - self, Architecture, ComdatKind, CompressedData, CompressedFileRange, Error, Export, FileFlags, - Import, NoDynamicRelocationIterator, Object, ObjectComdat, ObjectKind, ObjectSection, - ObjectSegment, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Relocation, Result, - SectionFlags, SectionIndex, SectionKind, SegmentFlags, SymbolFlags, SymbolIndex, SymbolKind, - SymbolScope, SymbolSection, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(usize)] -enum SectionId { - Custom = 0, - Type = 1, - Import = 2, - Function = 3, - Table = 4, - Memory = 5, - Global = 6, - Export = 7, - Start = 8, - Element = 9, - Code = 10, - Data = 11, - DataCount = 12, -} -// Update this constant when adding new section id: -const MAX_SECTION_ID: usize = SectionId::DataCount as usize; - -/// A WebAssembly object file. -#[derive(Debug)] -pub struct WasmFile<'data, R = &'data [u8]> { - data: &'data [u8], - has_memory64: bool, - // All sections, including custom sections. - sections: Vec>, - // Indices into `sections` of sections with a non-zero id. - id_sections: Box<[Option; MAX_SECTION_ID + 1]>, - // Whether the file has DWARF information. - has_debug_symbols: bool, - // Symbols collected from imports, exports, code and name sections. - symbols: Vec>, - // Address of the function body for the entry point. - entry: u64, - marker: PhantomData, -} - -#[derive(Debug)] -struct SectionHeader<'data> { - id: SectionId, - range: Range, - name: &'data str, -} - -#[derive(Clone)] -enum LocalFunctionKind { - Unknown, - Exported { symbol_ids: Vec }, - Local { symbol_id: u32 }, -} - -impl ReadError for wasmparser::Result { - fn read_error(self, error: &'static str) -> Result { - self.map_err(|_| Error(error)) - } -} - -impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { - /// Parse the raw wasm data. - pub fn parse(data: R) -> Result { - let len = data.len().read_error("Unknown Wasm file size")?; - let data = data.read_bytes_at(0, len).read_error("Wasm read failed")?; - let parser = wp::Parser::new(0).parse_all(data); - - let mut file = WasmFile { - data, - has_memory64: false, - sections: Vec::new(), - id_sections: Default::default(), - has_debug_symbols: false, - symbols: Vec::new(), - entry: 0, - marker: PhantomData, - }; - - let mut main_file_symbol = Some(WasmSymbolInternal { - name: "", - address: 0, - size: 0, - kind: SymbolKind::File, - section: SymbolSection::None, - scope: SymbolScope::Compilation, - }); - - let mut imported_funcs_count = 0; - let mut local_func_kinds = Vec::new(); - let mut entry_func_id = None; - let mut code_range_start = 0; - let mut code_func_index = 0; - // One-to-one mapping of globals to their value (if the global is a constant integer). - let mut global_values = Vec::new(); - - for payload in parser { - let payload = payload.read_error("Invalid Wasm section header")?; - - match payload { - wp::Payload::TypeSection(section) => { - file.add_section(SectionId::Type, section.range(), ""); - } - wp::Payload::ImportSection(section) => { - file.add_section(SectionId::Import, section.range(), ""); - let mut last_module_name = None; - - for import in section { - let import = import.read_error("Couldn't read an import item")?; - let module_name = import.module; - - if last_module_name != Some(module_name) { - file.symbols.push(WasmSymbolInternal { - name: module_name, - address: 0, - size: 0, - kind: SymbolKind::File, - section: SymbolSection::None, - scope: SymbolScope::Dynamic, - }); - last_module_name = Some(module_name); - } - - let kind = match import.ty { - wp::TypeRef::Func(_) => { - imported_funcs_count += 1; - SymbolKind::Text - } - wp::TypeRef::Memory(memory) => { - file.has_memory64 |= memory.memory64; - SymbolKind::Data - } - wp::TypeRef::Table(_) | wp::TypeRef::Global(_) => SymbolKind::Data, - wp::TypeRef::Tag(_) => SymbolKind::Unknown, - }; - - file.symbols.push(WasmSymbolInternal { - name: import.name, - address: 0, - size: 0, - kind, - section: SymbolSection::Undefined, - scope: SymbolScope::Dynamic, - }); - } - } - wp::Payload::FunctionSection(section) => { - file.add_section(SectionId::Function, section.range(), ""); - local_func_kinds = - vec![LocalFunctionKind::Unknown; section.into_iter().count()]; - } - wp::Payload::TableSection(section) => { - file.add_section(SectionId::Table, section.range(), ""); - } - wp::Payload::MemorySection(section) => { - file.add_section(SectionId::Memory, section.range(), ""); - for memory in section { - let memory = memory.read_error("Couldn't read a memory item")?; - file.has_memory64 |= memory.memory64; - } - } - wp::Payload::GlobalSection(section) => { - file.add_section(SectionId::Global, section.range(), ""); - for global in section { - let global = global.read_error("Couldn't read a global item")?; - let mut address = None; - if !global.ty.mutable { - // There should be exactly one instruction. - let init = global.init_expr.get_operators_reader().read(); - address = match init.read_error("Couldn't read a global init expr")? { - wp::Operator::I32Const { value } => Some(value as u64), - wp::Operator::I64Const { value } => Some(value as u64), - _ => None, - }; - } - global_values.push(address); - } - } - wp::Payload::ExportSection(section) => { - file.add_section(SectionId::Export, section.range(), ""); - if let Some(main_file_symbol) = main_file_symbol.take() { - file.symbols.push(main_file_symbol); - } - - for export in section { - let export = export.read_error("Couldn't read an export item")?; - - let (kind, section_idx) = match export.kind { - wp::ExternalKind::Func => { - if let Some(local_func_id) = - export.index.checked_sub(imported_funcs_count) - { - let local_func_kind = - &mut local_func_kinds[local_func_id as usize]; - if let LocalFunctionKind::Unknown = local_func_kind { - *local_func_kind = LocalFunctionKind::Exported { - symbol_ids: Vec::new(), - }; - } - let symbol_ids = match local_func_kind { - LocalFunctionKind::Exported { symbol_ids } => symbol_ids, - _ => unreachable!(), - }; - symbol_ids.push(file.symbols.len() as u32); - } - (SymbolKind::Text, SectionId::Code) - } - wp::ExternalKind::Table - | wp::ExternalKind::Memory - | wp::ExternalKind::Global => (SymbolKind::Data, SectionId::Data), - // TODO - wp::ExternalKind::Tag => continue, - }; - - // Try to guess the symbol address. Rust and C export a global containing - // the address in linear memory of the symbol. - let mut address = 0; - if export.kind == wp::ExternalKind::Global { - if let Some(&Some(x)) = global_values.get(export.index as usize) { - address = x; - } - } - - file.symbols.push(WasmSymbolInternal { - name: export.name, - address, - size: 0, - kind, - section: SymbolSection::Section(SectionIndex(section_idx as usize)), - scope: SymbolScope::Dynamic, - }); - } - } - wp::Payload::StartSection { func, range, .. } => { - file.add_section(SectionId::Start, range, ""); - entry_func_id = Some(func); - } - wp::Payload::ElementSection(section) => { - file.add_section(SectionId::Element, section.range(), ""); - } - wp::Payload::CodeSectionStart { range, .. } => { - code_range_start = range.start; - file.add_section(SectionId::Code, range, ""); - if let Some(main_file_symbol) = main_file_symbol.take() { - file.symbols.push(main_file_symbol); - } - } - wp::Payload::CodeSectionEntry(body) => { - let i = code_func_index; - code_func_index += 1; - - let range = body.range(); - - let address = range.start as u64 - code_range_start as u64; - let size = (range.end - range.start) as u64; - - if entry_func_id == Some(i as u32) { - file.entry = address; - } - - let local_func_kind = &mut local_func_kinds[i]; - match local_func_kind { - LocalFunctionKind::Unknown => { - *local_func_kind = LocalFunctionKind::Local { - symbol_id: file.symbols.len() as u32, - }; - file.symbols.push(WasmSymbolInternal { - name: "", - address, - size, - kind: SymbolKind::Text, - section: SymbolSection::Section(SectionIndex( - SectionId::Code as usize, - )), - scope: SymbolScope::Compilation, - }); - } - LocalFunctionKind::Exported { symbol_ids } => { - for symbol_id in core::mem::take(symbol_ids) { - let export_symbol = &mut file.symbols[symbol_id as usize]; - export_symbol.address = address; - export_symbol.size = size; - } - } - _ => unreachable!(), - } - } - wp::Payload::DataSection(section) => { - file.add_section(SectionId::Data, section.range(), ""); - } - wp::Payload::DataCountSection { range, .. } => { - file.add_section(SectionId::DataCount, range, ""); - } - wp::Payload::CustomSection(section) => { - let name = section.name(); - let size = section.data().len(); - let mut range = section.range(); - range.start = range.end - size; - file.add_section(SectionId::Custom, range, name); - if name == "name" { - for name in - wp::NameSectionReader::new(section.data(), section.data_offset()) - { - // TODO: Right now, ill-formed name subsections - // are silently ignored in order to maintain - // compatibility with extended name sections, which - // are not yet supported by the version of - // `wasmparser` currently used. - // A better fix would be to update `wasmparser` to - // the newest version, but this requires - // a major rewrite of this file. - if let Ok(wp::Name::Function(name_map)) = name { - for naming in name_map { - let naming = - naming.read_error("Couldn't read a function name")?; - if let Some(local_index) = - naming.index.checked_sub(imported_funcs_count) - { - if let LocalFunctionKind::Local { symbol_id } = - local_func_kinds[local_index as usize] - { - file.symbols[symbol_id as usize].name = naming.name; - } - } - } - } - } - } else if name.starts_with(".debug_") { - file.has_debug_symbols = true; - } - } - _ => {} - } - } - - Ok(file) - } - - fn add_section(&mut self, id: SectionId, range: Range, name: &'data str) { - let section = SectionHeader { id, range, name }; - self.id_sections[id as usize] = Some(self.sections.len()); - self.sections.push(section); - } -} - -impl<'data, R> read::private::Sealed for WasmFile<'data, R> {} - -impl<'data, 'file, R: ReadRef<'data>> Object<'data, 'file> for WasmFile<'data, R> -where - 'data: 'file, - R: 'file, -{ - type Segment = WasmSegment<'data, 'file, R>; - type SegmentIterator = WasmSegmentIterator<'data, 'file, R>; - type Section = WasmSection<'data, 'file, R>; - type SectionIterator = WasmSectionIterator<'data, 'file, R>; - type Comdat = WasmComdat<'data, 'file, R>; - type ComdatIterator = WasmComdatIterator<'data, 'file, R>; - type Symbol = WasmSymbol<'data, 'file>; - type SymbolIterator = WasmSymbolIterator<'data, 'file>; - type SymbolTable = WasmSymbolTable<'data, 'file>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - #[inline] - fn architecture(&self) -> Architecture { - if self.has_memory64 { - Architecture::Wasm64 - } else { - Architecture::Wasm32 - } - } - - #[inline] - fn is_little_endian(&self) -> bool { - true - } - - #[inline] - fn is_64(&self) -> bool { - self.has_memory64 - } - - fn kind(&self) -> ObjectKind { - // TODO: check for `linking` custom section - ObjectKind::Unknown - } - - fn segments(&'file self) -> Self::SegmentIterator { - WasmSegmentIterator { file: self } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - self.sections() - .find(|section| section.name_bytes() == Ok(section_name)) - } - - fn section_by_index(&'file self, index: SectionIndex) -> Result> { - // TODO: Missing sections should return an empty section. - let id_section = self - .id_sections - .get(index.0) - .and_then(|x| *x) - .read_error("Invalid Wasm section index")?; - let section = self.sections.get(id_section).unwrap(); - Ok(WasmSection { - file: self, - section, - }) - } - - fn sections(&'file self) -> Self::SectionIterator { - WasmSectionIterator { - file: self, - sections: self.sections.iter(), - } - } - - fn comdats(&'file self) -> Self::ComdatIterator { - WasmComdatIterator { file: self } - } - - #[inline] - fn symbol_by_index(&'file self, index: SymbolIndex) -> Result> { - let symbol = self - .symbols - .get(index.0) - .read_error("Invalid Wasm symbol index")?; - Ok(WasmSymbol { index, symbol }) - } - - fn symbols(&'file self) -> Self::SymbolIterator { - WasmSymbolIterator { - symbols: self.symbols.iter().enumerate(), - } - } - - fn symbol_table(&'file self) -> Option> { - Some(WasmSymbolTable { - symbols: &self.symbols, - }) - } - - fn dynamic_symbols(&'file self) -> Self::SymbolIterator { - WasmSymbolIterator { - symbols: [].iter().enumerate(), - } - } - - #[inline] - fn dynamic_symbol_table(&'file self) -> Option> { - None - } - - #[inline] - fn dynamic_relocations(&self) -> Option { - None - } - - fn imports(&self) -> Result>> { - // TODO: return entries in the import section - Ok(Vec::new()) - } - - fn exports(&self) -> Result>> { - // TODO: return entries in the export section - Ok(Vec::new()) - } - - fn has_debug_symbols(&self) -> bool { - self.has_debug_symbols - } - - fn relative_address_base(&self) -> u64 { - 0 - } - - #[inline] - fn entry(&'file self) -> u64 { - self.entry - } - - #[inline] - fn flags(&self) -> FileFlags { - FileFlags::None - } -} - -/// An iterator for the segments in a [`WasmFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmSegmentIterator<'data, 'file, R = &'data [u8]> { - #[allow(unused)] - file: &'file WasmFile<'data, R>, -} - -impl<'data, 'file, R> Iterator for WasmSegmentIterator<'data, 'file, R> { - type Item = WasmSegment<'data, 'file, R>; - - #[inline] - fn next(&mut self) -> Option { - None - } -} - -/// A segment in a [`WasmFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmSegment<'data, 'file, R = &'data [u8]> { - #[allow(unused)] - file: &'file WasmFile<'data, R>, -} - -impl<'data, 'file, R> read::private::Sealed for WasmSegment<'data, 'file, R> {} - -impl<'data, 'file, R> ObjectSegment<'data> for WasmSegment<'data, 'file, R> { - #[inline] - fn address(&self) -> u64 { - unreachable!() - } - - #[inline] - fn size(&self) -> u64 { - unreachable!() - } - - #[inline] - fn align(&self) -> u64 { - unreachable!() - } - - #[inline] - fn file_range(&self) -> (u64, u64) { - unreachable!() - } - - fn data(&self) -> Result<&'data [u8]> { - unreachable!() - } - - fn data_range(&self, _address: u64, _size: u64) -> Result> { - unreachable!() - } - - #[inline] - fn name_bytes(&self) -> Result> { - unreachable!() - } - - #[inline] - fn name(&self) -> Result> { - unreachable!() - } - - #[inline] - fn flags(&self) -> SegmentFlags { - unreachable!() - } -} - -/// An iterator for the sections in a [`WasmFile`]. -#[derive(Debug)] -pub struct WasmSectionIterator<'data, 'file, R = &'data [u8]> { - file: &'file WasmFile<'data, R>, - sections: slice::Iter<'file, SectionHeader<'data>>, -} - -impl<'data, 'file, R> Iterator for WasmSectionIterator<'data, 'file, R> { - type Item = WasmSection<'data, 'file, R>; - - fn next(&mut self) -> Option { - let section = self.sections.next()?; - Some(WasmSection { - file: self.file, - section, - }) - } -} - -/// A section in a [`WasmFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct WasmSection<'data, 'file, R = &'data [u8]> { - file: &'file WasmFile<'data, R>, - section: &'file SectionHeader<'data>, -} - -impl<'data, 'file, R> read::private::Sealed for WasmSection<'data, 'file, R> {} - -impl<'data, 'file, R: ReadRef<'data>> ObjectSection<'data> for WasmSection<'data, 'file, R> { - type RelocationIterator = WasmRelocationIterator<'data, 'file, R>; - - #[inline] - fn index(&self) -> SectionIndex { - // Note that we treat all custom sections as index 0. - // This is ok because they are never looked up by index. - SectionIndex(self.section.id as usize) - } - - #[inline] - fn address(&self) -> u64 { - 0 - } - - #[inline] - fn size(&self) -> u64 { - let range = &self.section.range; - (range.end - range.start) as u64 - } - - #[inline] - fn align(&self) -> u64 { - 1 - } - - #[inline] - fn file_range(&self) -> Option<(u64, u64)> { - let range = &self.section.range; - Some((range.start as _, range.end as _)) - } - - #[inline] - fn data(&self) -> Result<&'data [u8]> { - let range = &self.section.range; - self.file - .data - .read_bytes_at(range.start as u64, range.end as u64 - range.start as u64) - .read_error("Invalid Wasm section size or offset") - } - - fn data_range(&self, _address: u64, _size: u64) -> Result> { - unimplemented!() - } - - #[inline] - fn compressed_file_range(&self) -> Result { - Ok(CompressedFileRange::none(self.file_range())) - } - - #[inline] - fn compressed_data(&self) -> Result> { - self.data().map(CompressedData::none) - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - self.name().map(str::as_bytes) - } - - #[inline] - fn name(&self) -> Result<&str> { - Ok(match self.section.id { - SectionId::Custom => self.section.name, - SectionId::Type => "", - SectionId::Import => "", - SectionId::Function => "", - SectionId::Table => "", - SectionId::Memory => "", - SectionId::Global => "", - SectionId::Export => "", - SectionId::Start => "", - SectionId::Element => "", - SectionId::Code => "", - SectionId::Data => "", - SectionId::DataCount => "", - }) - } - - #[inline] - fn segment_name_bytes(&self) -> Result> { - Ok(None) - } - - #[inline] - fn segment_name(&self) -> Result> { - Ok(None) - } - - #[inline] - fn kind(&self) -> SectionKind { - match self.section.id { - SectionId::Custom => match self.section.name { - "reloc." | "linking" => SectionKind::Linker, - _ => SectionKind::Other, - }, - SectionId::Type => SectionKind::Metadata, - SectionId::Import => SectionKind::Linker, - SectionId::Function => SectionKind::Metadata, - SectionId::Table => SectionKind::UninitializedData, - SectionId::Memory => SectionKind::UninitializedData, - SectionId::Global => SectionKind::Data, - SectionId::Export => SectionKind::Linker, - SectionId::Start => SectionKind::Linker, - SectionId::Element => SectionKind::Data, - SectionId::Code => SectionKind::Text, - SectionId::Data => SectionKind::Data, - SectionId::DataCount => SectionKind::UninitializedData, - } - } - - #[inline] - fn relocations(&self) -> WasmRelocationIterator<'data, 'file, R> { - WasmRelocationIterator(PhantomData) - } - - #[inline] - fn flags(&self) -> SectionFlags { - SectionFlags::None - } -} - -/// An iterator for the COMDAT section groups in a [`WasmFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmComdatIterator<'data, 'file, R = &'data [u8]> { - #[allow(unused)] - file: &'file WasmFile<'data, R>, -} - -impl<'data, 'file, R> Iterator for WasmComdatIterator<'data, 'file, R> { - type Item = WasmComdat<'data, 'file, R>; - - #[inline] - fn next(&mut self) -> Option { - None - } -} - -/// A COMDAT section group in a [`WasmFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmComdat<'data, 'file, R = &'data [u8]> { - #[allow(unused)] - file: &'file WasmFile<'data, R>, -} - -impl<'data, 'file, R> read::private::Sealed for WasmComdat<'data, 'file, R> {} - -impl<'data, 'file, R> ObjectComdat<'data> for WasmComdat<'data, 'file, R> { - type SectionIterator = WasmComdatSectionIterator<'data, 'file, R>; - - #[inline] - fn kind(&self) -> ComdatKind { - unreachable!(); - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - unreachable!(); - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - unreachable!(); - } - - #[inline] - fn name(&self) -> Result<&str> { - unreachable!(); - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - unreachable!(); - } -} - -/// An iterator for the sections in a COMDAT section group in a [`WasmFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmComdatSectionIterator<'data, 'file, R = &'data [u8]> { - #[allow(unused)] - file: &'file WasmFile<'data, R>, -} - -impl<'data, 'file, R> Iterator for WasmComdatSectionIterator<'data, 'file, R> { - type Item = SectionIndex; - - fn next(&mut self) -> Option { - None - } -} - -/// A symbol table in a [`WasmFile`]. -#[derive(Debug)] -pub struct WasmSymbolTable<'data, 'file> { - symbols: &'file [WasmSymbolInternal<'data>], -} - -impl<'data, 'file> read::private::Sealed for WasmSymbolTable<'data, 'file> {} - -impl<'data, 'file> ObjectSymbolTable<'data> for WasmSymbolTable<'data, 'file> { - type Symbol = WasmSymbol<'data, 'file>; - type SymbolIterator = WasmSymbolIterator<'data, 'file>; - - fn symbols(&self) -> Self::SymbolIterator { - WasmSymbolIterator { - symbols: self.symbols.iter().enumerate(), - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> Result { - let symbol = self - .symbols - .get(index.0) - .read_error("Invalid Wasm symbol index")?; - Ok(WasmSymbol { index, symbol }) - } -} - -/// An iterator for the symbols in a [`WasmFile`]. -#[derive(Debug)] -pub struct WasmSymbolIterator<'data, 'file> { - symbols: core::iter::Enumerate>>, -} - -impl<'data, 'file> Iterator for WasmSymbolIterator<'data, 'file> { - type Item = WasmSymbol<'data, 'file>; - - fn next(&mut self) -> Option { - let (index, symbol) = self.symbols.next()?; - Some(WasmSymbol { - index: SymbolIndex(index), - symbol, - }) - } -} - -/// A symbol in a [`WasmFile`]. -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Clone, Copy, Debug)] -pub struct WasmSymbol<'data, 'file> { - index: SymbolIndex, - symbol: &'file WasmSymbolInternal<'data>, -} - -#[derive(Clone, Debug)] -struct WasmSymbolInternal<'data> { - name: &'data str, - address: u64, - size: u64, - kind: SymbolKind, - section: SymbolSection, - scope: SymbolScope, -} - -impl<'data, 'file> read::private::Sealed for WasmSymbol<'data, 'file> {} - -impl<'data, 'file> ObjectSymbol<'data> for WasmSymbol<'data, 'file> { - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - #[inline] - fn name_bytes(&self) -> read::Result<&'data [u8]> { - Ok(self.symbol.name.as_bytes()) - } - - #[inline] - fn name(&self) -> read::Result<&'data str> { - Ok(self.symbol.name) - } - - #[inline] - fn address(&self) -> u64 { - self.symbol.address - } - - #[inline] - fn size(&self) -> u64 { - self.symbol.size - } - - #[inline] - fn kind(&self) -> SymbolKind { - self.symbol.kind - } - - #[inline] - fn section(&self) -> SymbolSection { - self.symbol.section - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.section == SymbolSection::Undefined - } - - #[inline] - fn is_definition(&self) -> bool { - (self.symbol.kind == SymbolKind::Text || self.symbol.kind == SymbolKind::Data) - && self.symbol.section != SymbolSection::Undefined - } - - #[inline] - fn is_common(&self) -> bool { - self.symbol.section == SymbolSection::Common - } - - #[inline] - fn is_weak(&self) -> bool { - false - } - - #[inline] - fn scope(&self) -> SymbolScope { - self.symbol.scope - } - - #[inline] - fn is_global(&self) -> bool { - self.symbol.scope != SymbolScope::Compilation - } - - #[inline] - fn is_local(&self) -> bool { - self.symbol.scope == SymbolScope::Compilation - } - - #[inline] - fn flags(&self) -> SymbolFlags { - SymbolFlags::None - } -} - -/// An iterator for the relocations for a [`WasmSection`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct WasmRelocationIterator<'data, 'file, R = &'data [u8]>( - PhantomData<(&'data (), &'file (), R)>, -); - -impl<'data, 'file, R> Iterator for WasmRelocationIterator<'data, 'file, R> { - type Item = (u64, Relocation); - - #[inline] - fn next(&mut self) -> Option { - None - } -} diff --git a/vendor/object/src/read/xcoff/comdat.rs b/vendor/object/src/read/xcoff/comdat.rs deleted file mode 100644 index 03e52bf..0000000 --- a/vendor/object/src/read/xcoff/comdat.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! XCOFF doesn't support the COMDAT section. - -use core::fmt::Debug; - -use crate::xcoff; - -use crate::read::{self, ComdatKind, ObjectComdat, ReadRef, Result, SectionIndex, SymbolIndex}; - -use super::{FileHeader, XcoffFile}; - -/// An iterator for the COMDAT section groups in a [`XcoffFile32`](super::XcoffFile32). -pub type XcoffComdatIterator32<'data, 'file, R = &'data [u8]> = - XcoffComdatIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the COMDAT section groups in a [`XcoffFile64`](super::XcoffFile64). -pub type XcoffComdatIterator64<'data, 'file, R = &'data [u8]> = - XcoffComdatIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the COMDAT section groups in a [`XcoffFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct XcoffComdatIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - pub(crate) file: &'file XcoffFile<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type Item = XcoffComdat<'data, 'file, Xcoff, R>; - - #[inline] - fn next(&mut self) -> Option { - None - } -} - -/// A COMDAT section group in a [`XcoffFile32`](super::XcoffFile32). -pub type XcoffComdat32<'data, 'file, R = &'data [u8]> = - XcoffComdat<'data, 'file, xcoff::FileHeader32, R>; - -/// A COMDAT section group in a [`XcoffFile64`](super::XcoffFile64). -pub type XcoffComdat64<'data, 'file, R = &'data [u8]> = - XcoffComdat<'data, 'file, xcoff::FileHeader64, R>; - -/// A COMDAT section group in a [`XcoffFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct XcoffComdat<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file XcoffFile<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffComdat<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Xcoff, R> ObjectComdat<'data> for XcoffComdat<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type SectionIterator = XcoffComdatSectionIterator<'data, 'file, Xcoff, R>; - - #[inline] - fn kind(&self) -> ComdatKind { - unreachable!(); - } - - #[inline] - fn symbol(&self) -> SymbolIndex { - unreachable!(); - } - - #[inline] - fn name_bytes(&self) -> Result<&[u8]> { - unreachable!(); - } - - #[inline] - fn name(&self) -> Result<&str> { - unreachable!(); - } - - #[inline] - fn sections(&self) -> Self::SectionIterator { - unreachable!(); - } -} - -/// An iterator for the sections in a COMDAT section group in a [`XcoffFile32`](super::XcoffFile32). -pub type XcoffComdatSectionIterator32<'data, 'file, R = &'data [u8]> = - XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the sections in a COMDAT section group in a [`XcoffFile64`](super::XcoffFile64). -pub type XcoffComdatSectionIterator64<'data, 'file, R = &'data [u8]> = - XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the sections in a COMDAT section group in a [`XcoffFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct XcoffComdatSectionIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - file: &'file XcoffFile<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatSectionIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type Item = SectionIndex; - - fn next(&mut self) -> Option { - None - } -} diff --git a/vendor/object/src/read/xcoff/file.rs b/vendor/object/src/read/xcoff/file.rs deleted file mode 100644 index 70d980a..0000000 --- a/vendor/object/src/read/xcoff/file.rs +++ /dev/null @@ -1,696 +0,0 @@ -use core::fmt::Debug; -use core::mem; - -use alloc::vec::Vec; - -use crate::read::{self, Error, NoDynamicRelocationIterator, Object, ReadError, ReadRef, Result}; - -use crate::{ - xcoff, Architecture, BigEndian as BE, FileFlags, ObjectKind, ObjectSection, Pod, SectionIndex, - SymbolIndex, -}; - -use super::{ - CsectAux, FileAux, SectionHeader, SectionTable, Symbol, SymbolTable, XcoffComdat, - XcoffComdatIterator, XcoffSection, XcoffSectionIterator, XcoffSegment, XcoffSegmentIterator, - XcoffSymbol, XcoffSymbolIterator, XcoffSymbolTable, -}; - -/// A 32-bit XCOFF object file. -/// -/// This is a file that starts with [`xcoff::FileHeader32`], and corresponds -/// to [`crate::FileKind::Xcoff32`]. -pub type XcoffFile32<'data, R = &'data [u8]> = XcoffFile<'data, xcoff::FileHeader32, R>; -/// A 64-bit XCOFF object file. -/// -/// This is a file that starts with [`xcoff::FileHeader64`], and corresponds -/// to [`crate::FileKind::Xcoff64`]. -pub type XcoffFile64<'data, R = &'data [u8]> = XcoffFile<'data, xcoff::FileHeader64, R>; - -/// A partially parsed XCOFF file. -/// -/// Most functionality is provided by the [`Object`] trait implementation. -#[derive(Debug)] -pub struct XcoffFile<'data, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) data: R, - pub(super) header: &'data Xcoff, - pub(super) aux_header: Option<&'data Xcoff::AuxHeader>, - pub(super) sections: SectionTable<'data, Xcoff>, - pub(super) symbols: SymbolTable<'data, Xcoff, R>, -} - -impl<'data, Xcoff, R> XcoffFile<'data, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - /// Parse the raw XCOFF file data. - pub fn parse(data: R) -> Result { - let mut offset = 0; - let header = Xcoff::parse(data, &mut offset)?; - let aux_header = header.aux_header(data, &mut offset)?; - let sections = header.sections(data, &mut offset)?; - let symbols = header.symbols(data)?; - - Ok(XcoffFile { - data, - header, - aux_header, - sections, - symbols, - }) - } - - /// Returns the raw data. - pub fn data(&self) -> R { - self.data - } - - /// Returns the raw XCOFF file header. - pub fn raw_header(&self) -> &'data Xcoff { - self.header - } -} - -impl<'data, Xcoff, R> read::private::Sealed for XcoffFile<'data, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Xcoff, R> Object<'data, 'file> for XcoffFile<'data, Xcoff, R> -where - 'data: 'file, - Xcoff: FileHeader, - R: 'file + ReadRef<'data>, -{ - type Segment = XcoffSegment<'data, 'file, Xcoff, R>; - type SegmentIterator = XcoffSegmentIterator<'data, 'file, Xcoff, R>; - type Section = XcoffSection<'data, 'file, Xcoff, R>; - type SectionIterator = XcoffSectionIterator<'data, 'file, Xcoff, R>; - type Comdat = XcoffComdat<'data, 'file, Xcoff, R>; - type ComdatIterator = XcoffComdatIterator<'data, 'file, Xcoff, R>; - type Symbol = XcoffSymbol<'data, 'file, Xcoff, R>; - type SymbolIterator = XcoffSymbolIterator<'data, 'file, Xcoff, R>; - type SymbolTable = XcoffSymbolTable<'data, 'file, Xcoff, R>; - type DynamicRelocationIterator = NoDynamicRelocationIterator; - - fn architecture(&self) -> crate::Architecture { - if self.is_64() { - Architecture::PowerPc64 - } else { - Architecture::PowerPc - } - } - - fn is_little_endian(&self) -> bool { - false - } - - fn is_64(&self) -> bool { - self.header.is_type_64() - } - - fn kind(&self) -> ObjectKind { - let flags = self.header.f_flags(); - if flags & xcoff::F_EXEC != 0 { - ObjectKind::Executable - } else if flags & xcoff::F_SHROBJ != 0 { - ObjectKind::Dynamic - } else if flags & xcoff::F_RELFLG == 0 { - ObjectKind::Relocatable - } else { - ObjectKind::Unknown - } - } - - fn segments(&'file self) -> XcoffSegmentIterator<'data, 'file, Xcoff, R> { - XcoffSegmentIterator { file: self } - } - - fn section_by_name_bytes( - &'file self, - section_name: &[u8], - ) -> Option> { - self.sections() - .find(|section| section.name_bytes() == Ok(section_name)) - } - - fn section_by_index( - &'file self, - index: SectionIndex, - ) -> Result> { - let section = self.sections.section(index)?; - Ok(XcoffSection { - file: self, - section, - index, - }) - } - - fn sections(&'file self) -> XcoffSectionIterator<'data, 'file, Xcoff, R> { - XcoffSectionIterator { - file: self, - iter: self.sections.iter().enumerate(), - } - } - - fn comdats(&'file self) -> XcoffComdatIterator<'data, 'file, Xcoff, R> { - XcoffComdatIterator { file: self } - } - - fn symbol_table(&'file self) -> Option> { - if self.symbols.is_empty() { - return None; - } - Some(XcoffSymbolTable { - symbols: &self.symbols, - file: self, - }) - } - - fn symbol_by_index( - &'file self, - index: SymbolIndex, - ) -> Result> { - let symbol = self.symbols.symbol(index.0)?; - Ok(XcoffSymbol { - symbols: &self.symbols, - index, - symbol, - file: self, - }) - } - - fn symbols(&'file self) -> XcoffSymbolIterator<'data, 'file, Xcoff, R> { - XcoffSymbolIterator { - file: self, - symbols: self.symbols.iter(), - } - } - - fn dynamic_symbol_table(&'file self) -> Option> { - None - } - - fn dynamic_symbols(&'file self) -> XcoffSymbolIterator<'data, 'file, Xcoff, R> { - // TODO: return the symbols in the STYP_LOADER section. - XcoffSymbolIterator { - file: self, - symbols: self.symbols.iter_none(), - } - } - - fn dynamic_relocations(&'file self) -> Option { - // TODO: return the relocations in the STYP_LOADER section. - None - } - - fn imports(&self) -> Result>> { - // TODO: return the imports in the STYP_LOADER section. - Ok(Vec::new()) - } - - fn exports(&self) -> Result>> { - // TODO: return the exports in the STYP_LOADER section. - Ok(Vec::new()) - } - - fn has_debug_symbols(&self) -> bool { - self.section_by_name(".debug").is_some() || self.section_by_name(".dwinfo").is_some() - } - - fn relative_address_base(&'file self) -> u64 { - 0 - } - - fn entry(&'file self) -> u64 { - if let Some(aux_header) = self.aux_header { - aux_header.o_entry().into() - } else { - 0 - } - } - - fn flags(&self) -> FileFlags { - FileFlags::Xcoff { - f_flags: self.header.f_flags(), - } - } -} - -/// A trait for generic access to [`xcoff::FileHeader32`] and [`xcoff::FileHeader64`]. -#[allow(missing_docs)] -pub trait FileHeader: Debug + Pod { - type Word: Into; - type AuxHeader: AuxHeader; - type SectionHeader: SectionHeader; - type Symbol: Symbol; - type FileAux: FileAux; - type CsectAux: CsectAux; - - /// Return true if this type is a 64-bit header. - fn is_type_64(&self) -> bool; - - fn f_magic(&self) -> u16; - fn f_nscns(&self) -> u16; - fn f_timdat(&self) -> u32; - fn f_symptr(&self) -> Self::Word; - fn f_nsyms(&self) -> u32; - fn f_opthdr(&self) -> u16; - fn f_flags(&self) -> u16; - - // Provided methods. - - /// Read the file header. - /// - /// Also checks that the magic field in the file header is a supported format. - fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> { - let header = data - .read::(offset) - .read_error("Invalid XCOFF header size or alignment")?; - if !header.is_supported() { - return Err(Error("Unsupported XCOFF header")); - } - Ok(header) - } - - fn is_supported(&self) -> bool { - (self.is_type_64() && self.f_magic() == xcoff::MAGIC_64) - || (!self.is_type_64() && self.f_magic() == xcoff::MAGIC_32) - } - - /// Read the auxiliary file header. - fn aux_header<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: &mut u64, - ) -> Result> { - let aux_header_size = self.f_opthdr(); - if self.f_flags() & xcoff::F_EXEC == 0 { - // No auxiliary header is required for an object file that is not an executable. - // TODO: Some AIX programs generate auxiliary headers for 32-bit object files - // that end after the data_start field. - *offset += u64::from(aux_header_size); - return Ok(None); - } - // Executables, however, must have auxiliary headers that include the - // full structure definitions. - if aux_header_size != mem::size_of::() as u16 { - *offset += u64::from(aux_header_size); - return Ok(None); - } - let aux_header = data - .read::(offset) - .read_error("Invalid XCOFF auxiliary header size")?; - Ok(Some(aux_header)) - } - - /// Read the section table. - #[inline] - fn sections<'data, R: ReadRef<'data>>( - &self, - data: R, - offset: &mut u64, - ) -> Result> { - SectionTable::parse(self, data, offset) - } - - /// Return the symbol table. - #[inline] - fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> Result> { - SymbolTable::parse(*self, data) - } -} - -impl FileHeader for xcoff::FileHeader32 { - type Word = u32; - type AuxHeader = xcoff::AuxHeader32; - type SectionHeader = xcoff::SectionHeader32; - type Symbol = xcoff::Symbol32; - type FileAux = xcoff::FileAux32; - type CsectAux = xcoff::CsectAux32; - - fn is_type_64(&self) -> bool { - false - } - - fn f_magic(&self) -> u16 { - self.f_magic.get(BE) - } - - fn f_nscns(&self) -> u16 { - self.f_nscns.get(BE) - } - - fn f_timdat(&self) -> u32 { - self.f_timdat.get(BE) - } - - fn f_symptr(&self) -> Self::Word { - self.f_symptr.get(BE) - } - - fn f_nsyms(&self) -> u32 { - self.f_nsyms.get(BE) - } - - fn f_opthdr(&self) -> u16 { - self.f_opthdr.get(BE) - } - - fn f_flags(&self) -> u16 { - self.f_flags.get(BE) - } -} - -impl FileHeader for xcoff::FileHeader64 { - type Word = u64; - type AuxHeader = xcoff::AuxHeader64; - type SectionHeader = xcoff::SectionHeader64; - type Symbol = xcoff::Symbol64; - type FileAux = xcoff::FileAux64; - type CsectAux = xcoff::CsectAux64; - - fn is_type_64(&self) -> bool { - true - } - - fn f_magic(&self) -> u16 { - self.f_magic.get(BE) - } - - fn f_nscns(&self) -> u16 { - self.f_nscns.get(BE) - } - - fn f_timdat(&self) -> u32 { - self.f_timdat.get(BE) - } - - fn f_symptr(&self) -> Self::Word { - self.f_symptr.get(BE) - } - - fn f_nsyms(&self) -> u32 { - self.f_nsyms.get(BE) - } - - fn f_opthdr(&self) -> u16 { - self.f_opthdr.get(BE) - } - - fn f_flags(&self) -> u16 { - self.f_flags.get(BE) - } -} - -/// A trait for generic access to [`xcoff::AuxHeader32`] and [`xcoff::AuxHeader64`]. -#[allow(missing_docs)] -pub trait AuxHeader: Debug + Pod { - type Word: Into; - - fn o_mflag(&self) -> u16; - fn o_vstamp(&self) -> u16; - fn o_tsize(&self) -> Self::Word; - fn o_dsize(&self) -> Self::Word; - fn o_bsize(&self) -> Self::Word; - fn o_entry(&self) -> Self::Word; - fn o_text_start(&self) -> Self::Word; - fn o_data_start(&self) -> Self::Word; - fn o_toc(&self) -> Self::Word; - fn o_snentry(&self) -> u16; - fn o_sntext(&self) -> u16; - fn o_sndata(&self) -> u16; - fn o_sntoc(&self) -> u16; - fn o_snloader(&self) -> u16; - fn o_snbss(&self) -> u16; - fn o_algntext(&self) -> u16; - fn o_algndata(&self) -> u16; - fn o_modtype(&self) -> u16; - fn o_cpuflag(&self) -> u8; - fn o_cputype(&self) -> u8; - fn o_maxstack(&self) -> Self::Word; - fn o_maxdata(&self) -> Self::Word; - fn o_debugger(&self) -> u32; - fn o_textpsize(&self) -> u8; - fn o_datapsize(&self) -> u8; - fn o_stackpsize(&self) -> u8; - fn o_flags(&self) -> u8; - fn o_sntdata(&self) -> u16; - fn o_sntbss(&self) -> u16; - fn o_x64flags(&self) -> Option; -} - -impl AuxHeader for xcoff::AuxHeader32 { - type Word = u32; - - fn o_mflag(&self) -> u16 { - self.o_mflag.get(BE) - } - - fn o_vstamp(&self) -> u16 { - self.o_vstamp.get(BE) - } - - fn o_tsize(&self) -> Self::Word { - self.o_tsize.get(BE) - } - - fn o_dsize(&self) -> Self::Word { - self.o_dsize.get(BE) - } - - fn o_bsize(&self) -> Self::Word { - self.o_bsize.get(BE) - } - - fn o_entry(&self) -> Self::Word { - self.o_entry.get(BE) - } - - fn o_text_start(&self) -> Self::Word { - self.o_text_start.get(BE) - } - - fn o_data_start(&self) -> Self::Word { - self.o_data_start.get(BE) - } - - fn o_toc(&self) -> Self::Word { - self.o_toc.get(BE) - } - - fn o_snentry(&self) -> u16 { - self.o_snentry.get(BE) - } - - fn o_sntext(&self) -> u16 { - self.o_sntext.get(BE) - } - - fn o_sndata(&self) -> u16 { - self.o_sndata.get(BE) - } - - fn o_sntoc(&self) -> u16 { - self.o_sntoc.get(BE) - } - - fn o_snloader(&self) -> u16 { - self.o_snloader.get(BE) - } - - fn o_snbss(&self) -> u16 { - self.o_snbss.get(BE) - } - - fn o_algntext(&self) -> u16 { - self.o_algntext.get(BE) - } - - fn o_algndata(&self) -> u16 { - self.o_algndata.get(BE) - } - - fn o_modtype(&self) -> u16 { - self.o_modtype.get(BE) - } - - fn o_cpuflag(&self) -> u8 { - self.o_cpuflag - } - - fn o_cputype(&self) -> u8 { - self.o_cputype - } - - fn o_maxstack(&self) -> Self::Word { - self.o_maxstack.get(BE) - } - - fn o_maxdata(&self) -> Self::Word { - self.o_maxdata.get(BE) - } - - fn o_debugger(&self) -> u32 { - self.o_debugger.get(BE) - } - - fn o_textpsize(&self) -> u8 { - self.o_textpsize - } - - fn o_datapsize(&self) -> u8 { - self.o_datapsize - } - - fn o_stackpsize(&self) -> u8 { - self.o_stackpsize - } - - fn o_flags(&self) -> u8 { - self.o_flags - } - - fn o_sntdata(&self) -> u16 { - self.o_sntdata.get(BE) - } - - fn o_sntbss(&self) -> u16 { - self.o_sntbss.get(BE) - } - - fn o_x64flags(&self) -> Option { - None - } -} - -impl AuxHeader for xcoff::AuxHeader64 { - type Word = u64; - - fn o_mflag(&self) -> u16 { - self.o_mflag.get(BE) - } - - fn o_vstamp(&self) -> u16 { - self.o_vstamp.get(BE) - } - - fn o_tsize(&self) -> Self::Word { - self.o_tsize.get(BE) - } - - fn o_dsize(&self) -> Self::Word { - self.o_dsize.get(BE) - } - - fn o_bsize(&self) -> Self::Word { - self.o_bsize.get(BE) - } - - fn o_entry(&self) -> Self::Word { - self.o_entry.get(BE) - } - - fn o_text_start(&self) -> Self::Word { - self.o_text_start.get(BE) - } - - fn o_data_start(&self) -> Self::Word { - self.o_data_start.get(BE) - } - - fn o_toc(&self) -> Self::Word { - self.o_toc.get(BE) - } - - fn o_snentry(&self) -> u16 { - self.o_snentry.get(BE) - } - - fn o_sntext(&self) -> u16 { - self.o_sntext.get(BE) - } - - fn o_sndata(&self) -> u16 { - self.o_sndata.get(BE) - } - - fn o_sntoc(&self) -> u16 { - self.o_sntoc.get(BE) - } - - fn o_snloader(&self) -> u16 { - self.o_snloader.get(BE) - } - - fn o_snbss(&self) -> u16 { - self.o_snbss.get(BE) - } - - fn o_algntext(&self) -> u16 { - self.o_algntext.get(BE) - } - - fn o_algndata(&self) -> u16 { - self.o_algndata.get(BE) - } - - fn o_modtype(&self) -> u16 { - self.o_modtype.get(BE) - } - - fn o_cpuflag(&self) -> u8 { - self.o_cpuflag - } - - fn o_cputype(&self) -> u8 { - self.o_cputype - } - - fn o_maxstack(&self) -> Self::Word { - self.o_maxstack.get(BE) - } - - fn o_maxdata(&self) -> Self::Word { - self.o_maxdata.get(BE) - } - - fn o_debugger(&self) -> u32 { - self.o_debugger.get(BE) - } - - fn o_textpsize(&self) -> u8 { - self.o_textpsize - } - - fn o_datapsize(&self) -> u8 { - self.o_datapsize - } - - fn o_stackpsize(&self) -> u8 { - self.o_stackpsize - } - - fn o_flags(&self) -> u8 { - self.o_flags - } - - fn o_sntdata(&self) -> u16 { - self.o_sntdata.get(BE) - } - - fn o_sntbss(&self) -> u16 { - self.o_sntbss.get(BE) - } - - fn o_x64flags(&self) -> Option { - Some(self.o_x64flags.get(BE)) - } -} diff --git a/vendor/object/src/read/xcoff/mod.rs b/vendor/object/src/read/xcoff/mod.rs deleted file mode 100644 index b75c4da..0000000 --- a/vendor/object/src/read/xcoff/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Support for reading AIX XCOFF files. -//! -//! Traits are used to abstract over the difference between 32-bit and 64-bit XCOFF. -//! The primary trait for this is [`FileHeader`]. -//! -//! ## High level API -//! -//! [`XcoffFile`] implements the [`Object`](crate::read::Object) trait for XCOFF files. -//! [`XcoffFile`] is parameterised by [`FileHeader`] to allow reading both 32-bit and -//! 64-bit XCOFF. There are type aliases for these parameters ([`XcoffFile32`] and -//! [`XcoffFile64`]). -//! -//! ## Low level API -//! -//! The [`FileHeader`] trait can be directly used to parse both [`xcoff::FileHeader32`] -//! and [`xcoff::FileHeader64`]. -//! -//! ### Example for low level API -//! ```no_run -//! use object::xcoff; -//! use object::read::xcoff::{FileHeader, SectionHeader, Symbol}; -//! use std::error::Error; -//! use std::fs; -//! -//! /// Reads a file and displays the name of each section and symbol. -//! fn main() -> Result<(), Box> { -//! # #[cfg(feature = "std")] { -//! let data = fs::read("path/to/binary")?; -//! let mut offset = 0; -//! let header = xcoff::FileHeader64::parse(&*data, &mut offset)?; -//! let aux_header = header.aux_header(&*data, &mut offset)?; -//! let sections = header.sections(&*data, &mut offset)?; -//! let symbols = header.symbols(&*data)?; -//! for section in sections.iter() { -//! println!("{}", String::from_utf8_lossy(section.name())); -//! } -//! for (_index, symbol) in symbols.iter() { -//! println!("{}", String::from_utf8_lossy(symbol.name(symbols.strings())?)); -//! } -//! # } -//! Ok(()) -//! } -//! ``` -#[cfg(doc)] -use crate::xcoff; - -mod file; -pub use file::*; - -mod section; -pub use section::*; - -mod symbol; -pub use symbol::*; - -mod relocation; -pub use relocation::*; - -mod comdat; -pub use comdat::*; - -mod segment; -pub use segment::*; diff --git a/vendor/object/src/read/xcoff/relocation.rs b/vendor/object/src/read/xcoff/relocation.rs deleted file mode 100644 index a655ccc..0000000 --- a/vendor/object/src/read/xcoff/relocation.rs +++ /dev/null @@ -1,127 +0,0 @@ -use alloc::fmt; -use core::fmt::Debug; -use core::slice; - -use crate::pod::Pod; -use crate::{xcoff, BigEndian as BE, Relocation}; - -use crate::read::{ReadRef, RelocationEncoding, RelocationKind, RelocationTarget, SymbolIndex}; - -use super::{FileHeader, SectionHeader, XcoffFile}; - -/// An iterator for the relocations in an [`XcoffSection32`](super::XcoffSection32). -pub type XcoffRelocationIterator32<'data, 'file, R = &'data [u8]> = - XcoffRelocationIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the relocations in an [`XcoffSection64`](super::XcoffSection64). -pub type XcoffRelocationIterator64<'data, 'file, R = &'data [u8]> = - XcoffRelocationIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the relocations in an [`XcoffSection`](super::XcoffSection). -pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) relocations: - slice::Iter<'data, <::SectionHeader as SectionHeader>::Rel>, -} - -impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type Item = (u64, Relocation); - - fn next(&mut self) -> Option { - self.relocations.next().map(|relocation| { - let encoding = RelocationEncoding::Generic; - let (kind, addend) = match relocation.r_rtype() { - xcoff::R_POS - | xcoff::R_RL - | xcoff::R_RLA - | xcoff::R_BA - | xcoff::R_RBA - | xcoff::R_TLS => (RelocationKind::Absolute, 0), - xcoff::R_REL | xcoff::R_BR | xcoff::R_RBR => (RelocationKind::Relative, -4), - xcoff::R_TOC | xcoff::R_TOCL | xcoff::R_TOCU => (RelocationKind::Got, 0), - r_type => (RelocationKind::Xcoff(r_type), 0), - }; - let size = (relocation.r_rsize() & 0x3F) + 1; - let target = RelocationTarget::Symbol(SymbolIndex(relocation.r_symndx() as usize)); - ( - relocation.r_vaddr().into(), - Relocation { - kind, - encoding, - size, - target, - addend, - implicit_addend: true, - }, - ) - }) - } -} - -impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("XcoffRelocationIterator").finish() - } -} - -/// A trait for generic access to [`xcoff::Rel32`] and [`xcoff::Rel64`]. -#[allow(missing_docs)] -pub trait Rel: Debug + Pod { - type Word: Into; - fn r_vaddr(&self) -> Self::Word; - fn r_symndx(&self) -> u32; - fn r_rsize(&self) -> u8; - fn r_rtype(&self) -> u8; -} - -impl Rel for xcoff::Rel32 { - type Word = u32; - - fn r_vaddr(&self) -> Self::Word { - self.r_vaddr.get(BE) - } - - fn r_symndx(&self) -> u32 { - self.r_symndx.get(BE) - } - - fn r_rsize(&self) -> u8 { - self.r_rsize - } - - fn r_rtype(&self) -> u8 { - self.r_rtype - } -} - -impl Rel for xcoff::Rel64 { - type Word = u64; - - fn r_vaddr(&self) -> Self::Word { - self.r_vaddr.get(BE) - } - - fn r_symndx(&self) -> u32 { - self.r_symndx.get(BE) - } - - fn r_rsize(&self) -> u8 { - self.r_rsize - } - - fn r_rtype(&self) -> u8 { - self.r_rtype - } -} diff --git a/vendor/object/src/read/xcoff/section.rs b/vendor/object/src/read/xcoff/section.rs deleted file mode 100644 index 8a36bcf..0000000 --- a/vendor/object/src/read/xcoff/section.rs +++ /dev/null @@ -1,431 +0,0 @@ -use core::fmt::Debug; -use core::{iter, result, slice, str}; - -use crate::{ - xcoff, BigEndian as BE, CompressedData, CompressedFileRange, Pod, SectionFlags, SectionKind, -}; - -use crate::read::{self, Error, ObjectSection, ReadError, ReadRef, Result, SectionIndex}; - -use super::{AuxHeader, FileHeader, Rel, XcoffFile, XcoffRelocationIterator}; - -/// An iterator for the sections in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSectionIterator32<'data, 'file, R = &'data [u8]> = - XcoffSectionIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the sections in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSectionIterator64<'data, 'file, R = &'data [u8]> = - XcoffSectionIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the sections in an [`XcoffFile`]. -#[derive(Debug)] -pub struct XcoffSectionIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) iter: iter::Enumerate>, -} - -impl<'data, 'file, Xcoff, R> Iterator for XcoffSectionIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type Item = XcoffSection<'data, 'file, Xcoff, R>; - - fn next(&mut self) -> Option { - self.iter.next().map(|(index, section)| XcoffSection { - index: SectionIndex(index + 1), - file: self.file, - section, - }) - } -} - -/// A section in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSection32<'data, 'file, R = &'data [u8]> = - XcoffSection<'data, 'file, xcoff::FileHeader32, R>; -/// A section in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSection64<'data, 'file, R = &'data [u8]> = - XcoffSection<'data, 'file, xcoff::FileHeader64, R>; - -/// A section in an [`XcoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSection`] trait implementation. -#[derive(Debug)] -pub struct XcoffSection<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) section: &'data Xcoff::SectionHeader, - pub(super) index: SectionIndex, -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> XcoffSection<'data, 'file, Xcoff, R> { - fn bytes(&self) -> Result<&'data [u8]> { - self.section - .data(self.file.data) - .read_error("Invalid XCOFF section offset or size") - } -} - -impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffSection<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Xcoff, R> ObjectSection<'data> for XcoffSection<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type RelocationIterator = XcoffRelocationIterator<'data, 'file, Xcoff, R>; - - fn index(&self) -> SectionIndex { - self.index - } - - fn address(&self) -> u64 { - self.section.s_paddr().into() - } - - fn size(&self) -> u64 { - self.section.s_size().into() - } - - fn align(&self) -> u64 { - // The default section alignment is 4. - if let Some(aux_header) = self.file.aux_header { - match self.kind() { - SectionKind::Text => aux_header.o_algntext().into(), - SectionKind::Data => aux_header.o_algndata().into(), - _ => 4, - } - } else { - 4 - } - } - - fn file_range(&self) -> Option<(u64, u64)> { - self.section.file_range() - } - - fn data(&self) -> Result<&'data [u8]> { - self.bytes() - } - - fn data_range(&self, address: u64, size: u64) -> Result> { - Ok(read::util::data_range( - self.bytes()?, - self.address(), - address, - size, - )) - } - - fn compressed_file_range(&self) -> Result { - Ok(CompressedFileRange::none(self.file_range())) - } - - fn compressed_data(&self) -> Result> { - self.data().map(CompressedData::none) - } - - fn name_bytes(&self) -> read::Result<&[u8]> { - Ok(self.section.name()) - } - - fn name(&self) -> read::Result<&str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 XCOFF section name") - } - - fn segment_name_bytes(&self) -> Result> { - Ok(None) - } - - fn segment_name(&self) -> Result> { - Ok(None) - } - - fn kind(&self) -> SectionKind { - let section_type = self.section.s_flags() as u16; - if section_type & xcoff::STYP_TEXT != 0 { - SectionKind::Text - } else if section_type & xcoff::STYP_DATA != 0 { - SectionKind::Data - } else if section_type & xcoff::STYP_TDATA != 0 { - SectionKind::Tls - } else if section_type & xcoff::STYP_BSS != 0 { - SectionKind::UninitializedData - } else if section_type & xcoff::STYP_TBSS != 0 { - SectionKind::UninitializedTls - } else if section_type & (xcoff::STYP_DEBUG | xcoff::STYP_DWARF) != 0 { - SectionKind::Debug - } else if section_type & (xcoff::STYP_LOADER | xcoff::STYP_OVRFLO) != 0 { - SectionKind::Metadata - } else if section_type - & (xcoff::STYP_INFO | xcoff::STYP_EXCEPT | xcoff::STYP_PAD | xcoff::STYP_TYPCHK) - != 0 - { - SectionKind::Other - } else { - SectionKind::Unknown - } - } - - fn relocations(&self) -> Self::RelocationIterator { - let rel = self.section.relocations(self.file.data).unwrap_or(&[]); - XcoffRelocationIterator { - file: self.file, - relocations: rel.iter(), - } - } - - fn flags(&self) -> SectionFlags { - SectionFlags::Xcoff { - s_flags: self.section.s_flags(), - } - } - - fn uncompressed_data(&self) -> Result> { - self.compressed_data()?.decompress() - } -} - -/// The table of section headers in an XCOFF file. -/// -/// Returned by [`FileHeader::sections`]. -#[derive(Debug, Clone, Copy)] -pub struct SectionTable<'data, Xcoff: FileHeader> { - sections: &'data [Xcoff::SectionHeader], -} - -impl<'data, Xcoff> Default for SectionTable<'data, Xcoff> -where - Xcoff: FileHeader, -{ - fn default() -> Self { - Self { sections: &[] } - } -} - -impl<'data, Xcoff> SectionTable<'data, Xcoff> -where - Xcoff: FileHeader, -{ - /// Parse the section table. - /// - /// `data` must be the entire file data. - /// `offset` must be after the optional file header. - pub fn parse>(header: &Xcoff, data: R, offset: &mut u64) -> Result { - let section_num = header.f_nscns(); - if section_num == 0 { - return Ok(SectionTable::default()); - } - let sections = data - .read_slice(offset, section_num as usize) - .read_error("Invalid XCOFF section headers")?; - Ok(SectionTable { sections }) - } - - /// Iterate over the section headers. - #[inline] - pub fn iter(&self) -> slice::Iter<'data, Xcoff::SectionHeader> { - self.sections.iter() - } - - /// Return true if the section table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.sections.is_empty() - } - - /// The number of section headers. - #[inline] - pub fn len(&self) -> usize { - self.sections.len() - } - - /// Return the section header at the given index. - /// - /// The index is 1-based. - pub fn section(&self, index: SectionIndex) -> read::Result<&'data Xcoff::SectionHeader> { - self.sections - .get(index.0.wrapping_sub(1)) - .read_error("Invalid XCOFF section index") - } -} - -/// A trait for generic access to [`xcoff::SectionHeader32`] and [`xcoff::SectionHeader64`]. -#[allow(missing_docs)] -pub trait SectionHeader: Debug + Pod { - type Word: Into; - type HalfWord: Into; - type Xcoff: FileHeader; - type Rel: Rel; - - fn s_name(&self) -> &[u8; 8]; - fn s_paddr(&self) -> Self::Word; - fn s_vaddr(&self) -> Self::Word; - fn s_size(&self) -> Self::Word; - fn s_scnptr(&self) -> Self::Word; - fn s_relptr(&self) -> Self::Word; - fn s_lnnoptr(&self) -> Self::Word; - fn s_nreloc(&self) -> Self::HalfWord; - fn s_nlnno(&self) -> Self::HalfWord; - fn s_flags(&self) -> u32; - - /// Return the section name. - fn name(&self) -> &[u8] { - let sectname = &self.s_name()[..]; - match memchr::memchr(b'\0', sectname) { - Some(end) => §name[..end], - None => sectname, - } - } - - /// Return the offset and size of the section in the file. - fn file_range(&self) -> Option<(u64, u64)> { - Some((self.s_scnptr().into(), self.s_size().into())) - } - - /// Return the section data. - /// - /// Returns `Ok(&[])` if the section has no data. - /// Returns `Err` for invalid values. - fn data<'data, R: ReadRef<'data>>(&self, data: R) -> result::Result<&'data [u8], ()> { - if let Some((offset, size)) = self.file_range() { - data.read_bytes_at(offset, size) - } else { - Ok(&[]) - } - } - - /// Read the relocations. - fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]>; -} - -impl SectionHeader for xcoff::SectionHeader32 { - type Word = u32; - type HalfWord = u16; - type Xcoff = xcoff::FileHeader32; - type Rel = xcoff::Rel32; - - fn s_name(&self) -> &[u8; 8] { - &self.s_name - } - - fn s_paddr(&self) -> Self::Word { - self.s_paddr.get(BE) - } - - fn s_vaddr(&self) -> Self::Word { - self.s_vaddr.get(BE) - } - - fn s_size(&self) -> Self::Word { - self.s_size.get(BE) - } - - fn s_scnptr(&self) -> Self::Word { - self.s_scnptr.get(BE) - } - - fn s_relptr(&self) -> Self::Word { - self.s_relptr.get(BE) - } - - fn s_lnnoptr(&self) -> Self::Word { - self.s_lnnoptr.get(BE) - } - - fn s_nreloc(&self) -> Self::HalfWord { - self.s_nreloc.get(BE) - } - - fn s_nlnno(&self) -> Self::HalfWord { - self.s_nlnno.get(BE) - } - - fn s_flags(&self) -> u32 { - self.s_flags.get(BE) - } - - /// Read the relocations in a XCOFF32 file. - /// - /// `data` must be the entire file data. - fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]> { - let reloc_num = self.s_nreloc() as usize; - // TODO: If more than 65,534 relocation entries are required, the field value will be 65535, - // and an STYP_OVRFLO section header will contain the actual count of relocation entries in - // the s_paddr field. - if reloc_num == 65535 { - return Err(Error("Overflow section is not supported yet.")); - } - data.read_slice_at(self.s_relptr().into(), reloc_num) - .read_error("Invalid XCOFF relocation offset or number") - } -} - -impl SectionHeader for xcoff::SectionHeader64 { - type Word = u64; - type HalfWord = u32; - type Xcoff = xcoff::FileHeader64; - type Rel = xcoff::Rel64; - - fn s_name(&self) -> &[u8; 8] { - &self.s_name - } - - fn s_paddr(&self) -> Self::Word { - self.s_paddr.get(BE) - } - - fn s_vaddr(&self) -> Self::Word { - self.s_vaddr.get(BE) - } - - fn s_size(&self) -> Self::Word { - self.s_size.get(BE) - } - - fn s_scnptr(&self) -> Self::Word { - self.s_scnptr.get(BE) - } - - fn s_relptr(&self) -> Self::Word { - self.s_relptr.get(BE) - } - - fn s_lnnoptr(&self) -> Self::Word { - self.s_lnnoptr.get(BE) - } - - fn s_nreloc(&self) -> Self::HalfWord { - self.s_nreloc.get(BE) - } - - fn s_nlnno(&self) -> Self::HalfWord { - self.s_nlnno.get(BE) - } - - fn s_flags(&self) -> u32 { - self.s_flags.get(BE) - } - - /// Read the relocations in a XCOFF64 file. - /// - /// `data` must be the entire file data. - fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]> { - data.read_slice_at(self.s_relptr(), self.s_nreloc() as usize) - .read_error("Invalid XCOFF relocation offset or number") - } -} diff --git a/vendor/object/src/read/xcoff/segment.rs b/vendor/object/src/read/xcoff/segment.rs deleted file mode 100644 index d30d7d8..0000000 --- a/vendor/object/src/read/xcoff/segment.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! TODO: Support the segment for XCOFF when auxiliary file header and loader section is ready. - -use core::fmt::Debug; -use core::str; - -use crate::read::{self, ObjectSegment, ReadRef, Result}; -use crate::xcoff; - -use super::{FileHeader, XcoffFile}; - -/// An iterator for the segments in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSegmentIterator32<'data, 'file, R = &'data [u8]> = - XcoffSegmentIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the segments in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSegmentIterator64<'data, 'file, R = &'data [u8]> = - XcoffSegmentIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the segments in an [`XcoffFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct XcoffSegmentIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff, R> Iterator for XcoffSegmentIterator<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - type Item = XcoffSegment<'data, 'file, Xcoff, R>; - - fn next(&mut self) -> Option { - None - } -} - -/// A segment in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSegment32<'data, 'file, R = &'data [u8]> = - XcoffSegment<'data, 'file, xcoff::FileHeader32, R>; -/// A segment in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSegment64<'data, 'file, R = &'data [u8]> = - XcoffSegment<'data, 'file, xcoff::FileHeader64, R>; - -/// A loadable section in an [`XcoffFile`]. -/// -/// This is a stub that doesn't implement any functionality. -#[derive(Debug)] -pub struct XcoffSegment<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - #[allow(unused)] - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff, R> XcoffSegment<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffSegment<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ -} - -impl<'data, 'file, Xcoff, R> ObjectSegment<'data> for XcoffSegment<'data, 'file, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - fn address(&self) -> u64 { - unreachable!(); - } - - fn size(&self) -> u64 { - unreachable!(); - } - - fn align(&self) -> u64 { - unreachable!(); - } - - fn file_range(&self) -> (u64, u64) { - unreachable!(); - } - - fn data(&self) -> Result<&'data [u8]> { - unreachable!(); - } - - fn data_range(&self, _address: u64, _size: u64) -> Result> { - unreachable!(); - } - - fn name_bytes(&self) -> Result> { - unreachable!(); - } - - fn name(&self) -> Result> { - unreachable!(); - } - - fn flags(&self) -> crate::SegmentFlags { - unreachable!(); - } -} diff --git a/vendor/object/src/read/xcoff/symbol.rs b/vendor/object/src/read/xcoff/symbol.rs deleted file mode 100644 index 72651c3..0000000 --- a/vendor/object/src/read/xcoff/symbol.rs +++ /dev/null @@ -1,786 +0,0 @@ -use alloc::fmt; -use core::convert::TryInto; -use core::fmt::Debug; -use core::marker::PhantomData; -use core::str; - -use crate::endian::{BigEndian as BE, U32Bytes}; -use crate::pod::{bytes_of, Pod}; -use crate::read::util::StringTable; -use crate::xcoff; - -use crate::read::{ - self, Bytes, Error, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex, - SymbolFlags, SymbolIndex, SymbolKind, SymbolScope, SymbolSection, -}; - -use super::{FileHeader, XcoffFile}; - -/// A table of symbol entries in an XCOFF file. -/// -/// Also includes the string table used for the symbol names. -/// -/// Returned by [`FileHeader::symbols`]. -#[derive(Debug)] -pub struct SymbolTable<'data, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - symbols: &'data [xcoff::SymbolBytes], - strings: StringTable<'data, R>, - header: PhantomData, -} - -impl<'data, Xcoff, R> Default for SymbolTable<'data, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - fn default() -> Self { - Self { - symbols: &[], - strings: StringTable::default(), - header: PhantomData, - } - } -} - -impl<'data, Xcoff, R> SymbolTable<'data, Xcoff, R> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - /// Parse the symbol table. - pub fn parse(header: Xcoff, data: R) -> Result { - let mut offset = header.f_symptr().into(); - let (symbols, strings) = if offset != 0 { - let symbols = data - .read_slice(&mut offset, header.f_nsyms() as usize) - .read_error("Invalid XCOFF symbol table offset or size")?; - - // Parse the string table. - // Note: don't update data when reading length; the length includes itself. - let length = data - .read_at::>(offset) - .read_error("Missing XCOFF string table")? - .get(BE); - let str_end = offset - .checked_add(length as u64) - .read_error("Invalid XCOFF string table length")?; - let strings = StringTable::new(data, offset, str_end); - - (symbols, strings) - } else { - (&[][..], StringTable::default()) - }; - - Ok(SymbolTable { - symbols, - strings, - header: PhantomData, - }) - } - - /// Return the string table used for the symbol names. - #[inline] - pub fn strings(&self) -> StringTable<'data, R> { - self.strings - } - - /// Iterate over the symbols. - #[inline] - pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, Xcoff, R> { - SymbolIterator { - symbols: self, - index: 0, - } - } - - /// Empty symbol iterator. - #[inline] - pub(super) fn iter_none<'table>(&'table self) -> SymbolIterator<'data, 'table, Xcoff, R> { - SymbolIterator { - symbols: self, - index: self.symbols.len(), - } - } - - /// Return the symbol entry at the given index and offset. - pub fn get(&self, index: usize, offset: usize) -> Result<&'data T> { - let entry = index - .checked_add(offset) - .and_then(|x| self.symbols.get(x)) - .read_error("Invalid XCOFF symbol index")?; - let bytes = bytes_of(entry); - Bytes(bytes).read().read_error("Invalid XCOFF symbol data") - } - - /// Return the symbol at the given index. - pub fn symbol(&self, index: usize) -> Result<&'data Xcoff::Symbol> { - self.get::(index, 0) - } - - /// Return a file auxiliary symbol. - pub fn aux_file(&self, index: usize, offset: usize) -> Result<&'data Xcoff::FileAux> { - debug_assert!(self.symbol(index)?.has_aux_file()); - let aux_file = self.get::(index, offset)?; - if let Some(aux_type) = aux_file.x_auxtype() { - if aux_type != xcoff::AUX_FILE { - return Err(Error("Invalid index for file auxiliary symbol.")); - } - } - Ok(aux_file) - } - - /// Return the csect auxiliary symbol. - pub fn aux_csect(&self, index: usize, offset: usize) -> Result<&'data Xcoff::CsectAux> { - debug_assert!(self.symbol(index)?.has_aux_csect()); - let aux_csect = self.get::(index, offset)?; - if let Some(aux_type) = aux_csect.x_auxtype() { - if aux_type != xcoff::AUX_CSECT { - return Err(Error("Invalid index/offset for csect auxiliary symbol.")); - } - } - Ok(aux_csect) - } - - /// Return true if the symbol table is empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.symbols.is_empty() - } - - /// The number of symbol table entries. - /// - /// This includes auxiliary symbol table entries. - #[inline] - pub fn len(&self) -> usize { - self.symbols.len() - } -} - -/// An iterator for symbol entries in an XCOFF file. -/// -/// Yields the index and symbol structure for each symbol. -#[derive(Debug)] -pub struct SymbolIterator<'data, 'table, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - symbols: &'table SymbolTable<'data, Xcoff, R>, - index: usize, -} - -impl<'data, 'table, Xcoff: FileHeader, R: ReadRef<'data>> Iterator - for SymbolIterator<'data, 'table, Xcoff, R> -{ - type Item = (SymbolIndex, &'data Xcoff::Symbol); - - fn next(&mut self) -> Option { - let index = self.index; - let symbol = self.symbols.symbol(index).ok()?; - self.index += 1 + symbol.n_numaux() as usize; - Some((SymbolIndex(index), symbol)) - } -} - -/// A symbol table in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSymbolTable32<'data, 'file, R = &'data [u8]> = - XcoffSymbolTable<'data, 'file, xcoff::FileHeader32, R>; -/// A symbol table in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSymbolTable64<'data, 'file, R = &'data [u8]> = - XcoffSymbolTable<'data, 'file, xcoff::FileHeader64, R>; - -/// A symbol table in an [`XcoffFile`]. -#[derive(Debug, Clone, Copy)] -pub struct XcoffSymbolTable<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>, -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed - for XcoffSymbolTable<'data, 'file, Xcoff, R> -{ -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data> - for XcoffSymbolTable<'data, 'file, Xcoff, R> -{ - type Symbol = XcoffSymbol<'data, 'file, Xcoff, R>; - type SymbolIterator = XcoffSymbolIterator<'data, 'file, Xcoff, R>; - - fn symbols(&self) -> Self::SymbolIterator { - XcoffSymbolIterator { - file: self.file, - symbols: self.symbols.iter(), - } - } - - fn symbol_by_index(&self, index: SymbolIndex) -> read::Result { - let symbol = self.symbols.symbol(index.0)?; - Ok(XcoffSymbol { - file: self.file, - symbols: self.symbols, - index, - symbol, - }) - } -} - -/// An iterator for the symbols in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSymbolIterator32<'data, 'file, R = &'data [u8]> = - XcoffSymbolIterator<'data, 'file, xcoff::FileHeader32, R>; -/// An iterator for the symbols in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSymbolIterator64<'data, 'file, R = &'data [u8]> = - XcoffSymbolIterator<'data, 'file, xcoff::FileHeader64, R>; - -/// An iterator for the symbols in an [`XcoffFile`]. -pub struct XcoffSymbolIterator<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) symbols: SymbolIterator<'data, 'file, Xcoff, R>, -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> fmt::Debug - for XcoffSymbolIterator<'data, 'file, Xcoff, R> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("XcoffSymbolIterator").finish() - } -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> Iterator - for XcoffSymbolIterator<'data, 'file, Xcoff, R> -{ - type Item = XcoffSymbol<'data, 'file, Xcoff, R>; - - fn next(&mut self) -> Option { - let (index, symbol) = self.symbols.next()?; - Some(XcoffSymbol { - file: self.file, - symbols: self.symbols.symbols, - index, - symbol, - }) - } -} - -/// A symbol in an [`XcoffFile32`](super::XcoffFile32). -pub type XcoffSymbol32<'data, 'file, R = &'data [u8]> = - XcoffSymbol<'data, 'file, xcoff::FileHeader32, R>; -/// A symbol in an [`XcoffFile64`](super::XcoffFile64). -pub type XcoffSymbol64<'data, 'file, R = &'data [u8]> = - XcoffSymbol<'data, 'file, xcoff::FileHeader64, R>; - -/// A symbol in an [`XcoffFile`]. -/// -/// Most functionality is provided by the [`ObjectSymbol`] trait implementation. -#[derive(Debug, Clone, Copy)] -pub struct XcoffSymbol<'data, 'file, Xcoff, R = &'data [u8]> -where - Xcoff: FileHeader, - R: ReadRef<'data>, -{ - pub(super) file: &'file XcoffFile<'data, Xcoff, R>, - pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>, - pub(super) index: SymbolIndex, - pub(super) symbol: &'data Xcoff::Symbol, -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed - for XcoffSymbol<'data, 'file, Xcoff, R> -{ -} - -impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data> - for XcoffSymbol<'data, 'file, Xcoff, R> -{ - #[inline] - fn index(&self) -> SymbolIndex { - self.index - } - - fn name_bytes(&self) -> Result<&'data [u8]> { - if self.symbol.has_aux_file() { - // By convention the file name is in the first auxiliary entry. - self.symbols - .aux_file(self.index.0, 1)? - .fname(self.symbols.strings) - } else { - self.symbol.name(self.symbols.strings) - } - } - - fn name(&self) -> Result<&'data str> { - let name = self.name_bytes()?; - str::from_utf8(name) - .ok() - .read_error("Non UTF-8 XCOFF symbol name") - } - - #[inline] - fn address(&self) -> u64 { - match self.symbol.n_sclass() { - // Relocatable address. - xcoff::C_EXT - | xcoff::C_WEAKEXT - | xcoff::C_HIDEXT - | xcoff::C_FCN - | xcoff::C_BLOCK - | xcoff::C_STAT - | xcoff::C_INFO => self.symbol.n_value().into(), - _ => 0, - } - } - - #[inline] - fn size(&self) -> u64 { - if self.symbol.has_aux_csect() { - // XCOFF32 must have the csect auxiliary entry as the last auxiliary entry. - // XCOFF64 doesn't require this, but conventionally does. - if let Ok(aux_csect) = self - .file - .symbols - .aux_csect(self.index.0, self.symbol.n_numaux() as usize) - { - let sym_type = aux_csect.sym_type(); - if sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_CM { - return aux_csect.x_scnlen(); - } - } - } - 0 - } - - fn kind(&self) -> SymbolKind { - if self.symbol.has_aux_csect() { - if let Ok(aux_csect) = self - .file - .symbols - .aux_csect(self.index.0, self.symbol.n_numaux() as usize) - { - let sym_type = aux_csect.sym_type(); - if sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_CM { - return match aux_csect.x_smclas() { - xcoff::XMC_PR | xcoff::XMC_GL => SymbolKind::Text, - xcoff::XMC_RO | xcoff::XMC_RW | xcoff::XMC_TD | xcoff::XMC_BS => { - SymbolKind::Data - } - xcoff::XMC_TL | xcoff::XMC_UL => SymbolKind::Tls, - xcoff::XMC_DS | xcoff::XMC_TC0 | xcoff::XMC_TC => { - // `Metadata` might be a better kind for these if we had it. - SymbolKind::Data - } - _ => SymbolKind::Unknown, - }; - } else if sym_type == xcoff::XTY_LD { - // A function entry point. Neither `Text` nor `Label` are a good fit for this. - return SymbolKind::Text; - } else if sym_type == xcoff::XTY_ER { - return SymbolKind::Unknown; - } - } - } - match self.symbol.n_sclass() { - xcoff::C_NULL => SymbolKind::Null, - xcoff::C_FILE => SymbolKind::File, - _ => SymbolKind::Unknown, - } - } - - fn section(&self) -> SymbolSection { - match self.symbol.n_scnum() { - xcoff::N_ABS => SymbolSection::Absolute, - xcoff::N_UNDEF => SymbolSection::Undefined, - xcoff::N_DEBUG => SymbolSection::None, - index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)), - _ => SymbolSection::Unknown, - } - } - - #[inline] - fn is_undefined(&self) -> bool { - self.symbol.is_undefined() - } - - /// Return true if the symbol is a definition of a function or data object. - #[inline] - fn is_definition(&self) -> bool { - if self.symbol.n_scnum() <= 0 { - return false; - } - if self.symbol.has_aux_csect() { - if let Ok(aux_csect) = self - .symbols - .aux_csect(self.index.0, self.symbol.n_numaux() as usize) - { - let sym_type = aux_csect.sym_type(); - sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_LD || sym_type == xcoff::XTY_CM - } else { - false - } - } else { - false - } - } - - #[inline] - fn is_common(&self) -> bool { - self.symbol.n_sclass() == xcoff::C_EXT && self.symbol.n_scnum() == xcoff::N_UNDEF - } - - #[inline] - fn is_weak(&self) -> bool { - self.symbol.n_sclass() == xcoff::C_WEAKEXT - } - - fn scope(&self) -> SymbolScope { - if self.symbol.n_scnum() == xcoff::N_UNDEF { - SymbolScope::Unknown - } else { - match self.symbol.n_sclass() { - xcoff::C_EXT | xcoff::C_WEAKEXT => { - let visibility = self.symbol.n_type() & xcoff::SYM_V_MASK; - if visibility == xcoff::SYM_V_HIDDEN { - SymbolScope::Linkage - } else { - SymbolScope::Dynamic - } - } - _ => SymbolScope::Compilation, - } - } - } - - #[inline] - fn is_global(&self) -> bool { - match self.symbol.n_sclass() { - xcoff::C_EXT | xcoff::C_WEAKEXT => true, - _ => false, - } - } - - #[inline] - fn is_local(&self) -> bool { - !self.is_global() - } - - #[inline] - fn flags(&self) -> SymbolFlags { - let mut x_smtyp = 0; - let mut x_smclas = 0; - let mut containing_csect = None; - if self.symbol.has_aux_csect() { - if let Ok(aux_csect) = self - .file - .symbols - .aux_csect(self.index.0, self.symbol.n_numaux() as usize) - { - x_smtyp = aux_csect.x_smtyp(); - x_smclas = aux_csect.x_smclas(); - if aux_csect.sym_type() == xcoff::XTY_LD { - containing_csect = Some(SymbolIndex(aux_csect.x_scnlen() as usize)) - } - } - } - SymbolFlags::Xcoff { - n_sclass: self.symbol.n_sclass(), - x_smtyp, - x_smclas, - containing_csect, - } - } -} - -/// A trait for generic access to [`xcoff::Symbol32`] and [`xcoff::Symbol64`]. -#[allow(missing_docs)] -pub trait Symbol: Debug + Pod { - type Word: Into; - - fn n_value(&self) -> Self::Word; - fn n_scnum(&self) -> i16; - fn n_type(&self) -> u16; - fn n_sclass(&self) -> u8; - fn n_numaux(&self) -> u8; - - fn name_offset(&self) -> Option; - fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]>; - - /// Return true if the symbol is undefined. - #[inline] - fn is_undefined(&self) -> bool { - let n_sclass = self.n_sclass(); - (n_sclass == xcoff::C_EXT || n_sclass == xcoff::C_WEAKEXT) - && self.n_scnum() == xcoff::N_UNDEF - } - - /// Return true if the symbol has file auxiliary entry. - fn has_aux_file(&self) -> bool { - self.n_numaux() > 0 && self.n_sclass() == xcoff::C_FILE - } - - /// Return true if the symbol has csect auxiliary entry. - /// - /// A csect auxiliary entry is required for each symbol table entry that has - /// a storage class value of C_EXT, C_WEAKEXT, or C_HIDEXT. - fn has_aux_csect(&self) -> bool { - let sclass = self.n_sclass(); - self.n_numaux() > 0 - && (sclass == xcoff::C_EXT || sclass == xcoff::C_WEAKEXT || sclass == xcoff::C_HIDEXT) - } -} - -impl Symbol for xcoff::Symbol64 { - type Word = u64; - - fn n_value(&self) -> Self::Word { - self.n_value.get(BE) - } - - fn n_scnum(&self) -> i16 { - self.n_scnum.get(BE) - } - - fn n_type(&self) -> u16 { - self.n_type.get(BE) - } - - fn n_sclass(&self) -> u8 { - self.n_sclass - } - - fn n_numaux(&self) -> u8 { - self.n_numaux - } - - fn name_offset(&self) -> Option { - Some(self.n_offset.get(BE)) - } - - /// Parse the symbol name for XCOFF64. - fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - strings - .get(self.n_offset.get(BE)) - .read_error("Invalid XCOFF symbol name offset") - } -} - -impl Symbol for xcoff::Symbol32 { - type Word = u32; - - fn n_value(&self) -> Self::Word { - self.n_value.get(BE) - } - - fn n_scnum(&self) -> i16 { - self.n_scnum.get(BE) - } - - fn n_type(&self) -> u16 { - self.n_type.get(BE) - } - - fn n_sclass(&self) -> u8 { - self.n_sclass - } - - fn n_numaux(&self) -> u8 { - self.n_numaux - } - - fn name_offset(&self) -> Option { - if self.n_name[0] == 0 { - let offset = u32::from_be_bytes(self.n_name[4..8].try_into().unwrap()); - Some(offset) - } else { - None - } - } - - /// Parse the symbol name for XCOFF32. - fn name<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - if let Some(offset) = self.name_offset() { - // If the name starts with 0 then the last 4 bytes are a string table offset. - strings - .get(offset) - .read_error("Invalid XCOFF symbol name offset") - } else { - // The name is inline and padded with nulls. - Ok(match memchr::memchr(b'\0', &self.n_name) { - Some(end) => &self.n_name[..end], - None => &self.n_name, - }) - } - } -} - -/// A trait for generic access to [`xcoff::FileAux32`] and [`xcoff::FileAux64`]. -#[allow(missing_docs)] -pub trait FileAux: Debug + Pod { - fn x_fname(&self) -> &[u8; 8]; - fn x_ftype(&self) -> u8; - fn x_auxtype(&self) -> Option; - - fn name_offset(&self) -> Option { - let x_fname = self.x_fname(); - if x_fname[0] == 0 { - Some(u32::from_be_bytes(x_fname[4..8].try_into().unwrap())) - } else { - None - } - } - - /// Parse the x_fname field, which may be an inline string or a string table offset. - fn fname<'data, R: ReadRef<'data>>( - &'data self, - strings: StringTable<'data, R>, - ) -> Result<&'data [u8]> { - if let Some(offset) = self.name_offset() { - // If the name starts with 0 then the last 4 bytes are a string table offset. - strings - .get(offset) - .read_error("Invalid XCOFF symbol name offset") - } else { - // The name is inline and padded with nulls. - let x_fname = self.x_fname(); - Ok(match memchr::memchr(b'\0', x_fname) { - Some(end) => &x_fname[..end], - None => x_fname, - }) - } - } -} - -impl FileAux for xcoff::FileAux64 { - fn x_fname(&self) -> &[u8; 8] { - &self.x_fname - } - - fn x_ftype(&self) -> u8 { - self.x_ftype - } - - fn x_auxtype(&self) -> Option { - Some(self.x_auxtype) - } -} - -impl FileAux for xcoff::FileAux32 { - fn x_fname(&self) -> &[u8; 8] { - &self.x_fname - } - - fn x_ftype(&self) -> u8 { - self.x_ftype - } - - fn x_auxtype(&self) -> Option { - None - } -} - -/// A trait for generic access to [`xcoff::CsectAux32`] and [`xcoff::CsectAux64`]. -#[allow(missing_docs)] -pub trait CsectAux: Debug + Pod { - fn x_scnlen(&self) -> u64; - fn x_parmhash(&self) -> u32; - fn x_snhash(&self) -> u16; - fn x_smtyp(&self) -> u8; - fn x_smclas(&self) -> u8; - fn x_stab(&self) -> Option; - fn x_snstab(&self) -> Option; - fn x_auxtype(&self) -> Option; - - fn alignment(&self) -> u8 { - self.x_smtyp() >> 3 - } - fn sym_type(&self) -> u8 { - self.x_smtyp() & 0x07 - } -} - -impl CsectAux for xcoff::CsectAux64 { - fn x_scnlen(&self) -> u64 { - self.x_scnlen_lo.get(BE) as u64 | ((self.x_scnlen_hi.get(BE) as u64) << 32) - } - - fn x_parmhash(&self) -> u32 { - self.x_parmhash.get(BE) - } - - fn x_snhash(&self) -> u16 { - self.x_snhash.get(BE) - } - - fn x_smtyp(&self) -> u8 { - self.x_smtyp - } - - fn x_smclas(&self) -> u8 { - self.x_smclas - } - - fn x_stab(&self) -> Option { - None - } - - fn x_snstab(&self) -> Option { - None - } - - fn x_auxtype(&self) -> Option { - Some(self.x_auxtype) - } -} - -impl CsectAux for xcoff::CsectAux32 { - fn x_scnlen(&self) -> u64 { - self.x_scnlen.get(BE) as u64 - } - - fn x_parmhash(&self) -> u32 { - self.x_parmhash.get(BE) - } - - fn x_snhash(&self) -> u16 { - self.x_snhash.get(BE) - } - - fn x_smtyp(&self) -> u8 { - self.x_smtyp - } - - fn x_smclas(&self) -> u8 { - self.x_smclas - } - - fn x_stab(&self) -> Option { - Some(self.x_stab.get(BE)) - } - - fn x_snstab(&self) -> Option { - Some(self.x_snstab.get(BE)) - } - - fn x_auxtype(&self) -> Option { - None - } -} diff --git a/vendor/object/src/write/coff/mod.rs b/vendor/object/src/write/coff/mod.rs deleted file mode 100644 index 6e0f5ed..0000000 --- a/vendor/object/src/write/coff/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Support for writing COFF files. -//! -//! Provides [`Writer`] for low level writing of COFF files. -//! This is also used to provide COFF support for [`write::Object`](crate::write::Object). - -mod object; -pub use self::object::*; - -mod writer; -pub use writer::*; diff --git a/vendor/object/src/write/coff/object.rs b/vendor/object/src/write/coff/object.rs deleted file mode 100644 index 5229665..0000000 --- a/vendor/object/src/write/coff/object.rs +++ /dev/null @@ -1,583 +0,0 @@ -use alloc::vec::Vec; - -use crate::pe as coff; -use crate::write::coff::writer; -use crate::write::util::*; -use crate::write::*; - -#[derive(Default, Clone, Copy)] -struct SectionOffsets { - name: writer::Name, - offset: u32, - reloc_offset: u32, - selection: u8, - associative_section: u32, -} - -#[derive(Default, Clone, Copy)] -struct SymbolOffsets { - name: writer::Name, - index: u32, - aux_count: u8, -} - -/// Internal format to use for the `.drectve` section containing linker -/// directives for symbol exports. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum CoffExportStyle { - /// MSVC format supported by link.exe and LLD. - Msvc, - /// Gnu format supported by GNU LD and LLD. - Gnu, -} - -impl<'a> Object<'a> { - pub(crate) fn coff_section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match section { - StandardSection::Text => (&[], &b".text"[..], SectionKind::Text, SectionFlags::None), - StandardSection::Data => (&[], &b".data"[..], SectionKind::Data, SectionFlags::None), - StandardSection::ReadOnlyData - | StandardSection::ReadOnlyDataWithRel - | StandardSection::ReadOnlyString => ( - &[], - &b".rdata"[..], - SectionKind::ReadOnlyData, - SectionFlags::None, - ), - StandardSection::UninitializedData => ( - &[], - &b".bss"[..], - SectionKind::UninitializedData, - SectionFlags::None, - ), - // TLS sections are data sections with a special name. - StandardSection::Tls => (&[], &b".tls$"[..], SectionKind::Data, SectionFlags::None), - StandardSection::UninitializedTls => { - // Unsupported section. - (&[], &[], SectionKind::UninitializedTls, SectionFlags::None) - } - StandardSection::TlsVariables => { - // Unsupported section. - (&[], &[], SectionKind::TlsVariables, SectionFlags::None) - } - StandardSection::Common => { - // Unsupported section. - (&[], &[], SectionKind::Common, SectionFlags::None) - } - StandardSection::GnuProperty => { - // Unsupported section. - (&[], &[], SectionKind::Note, SectionFlags::None) - } - } - } - - pub(crate) fn coff_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec { - let mut name = section.to_vec(); - name.push(b'$'); - name.extend_from_slice(value); - name - } - - pub(crate) fn coff_fixup_relocation(&mut self, relocation: &mut Relocation) -> i64 { - if relocation.kind == RelocationKind::GotRelative { - // Use a stub symbol for the relocation instead. - // This isn't really a GOT, but it's a similar purpose. - // TODO: need to handle DLL imports differently? - relocation.kind = RelocationKind::Relative; - relocation.symbol = self.coff_add_stub_symbol(relocation.symbol); - } else if relocation.kind == RelocationKind::PltRelative { - // Windows doesn't need a separate relocation type for - // references to functions in import libraries. - // For convenience, treat this the same as Relative. - relocation.kind = RelocationKind::Relative; - } - - let constant = match self.architecture { - Architecture::I386 | Architecture::Arm | Architecture::Aarch64 => match relocation.kind - { - RelocationKind::Relative => { - // IMAGE_REL_I386_REL32, IMAGE_REL_ARM_REL32, IMAGE_REL_ARM64_REL32 - relocation.addend + 4 - } - _ => relocation.addend, - }, - Architecture::X86_64 => match relocation.kind { - RelocationKind::Relative => { - // IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5 - if relocation.addend <= -4 && relocation.addend >= -9 { - 0 - } else { - relocation.addend + 4 - } - } - _ => relocation.addend, - }, - _ => unimplemented!(), - }; - relocation.addend -= constant; - constant - } - - fn coff_add_stub_symbol(&mut self, symbol_id: SymbolId) -> SymbolId { - if let Some(stub_id) = self.stub_symbols.get(&symbol_id) { - return *stub_id; - } - let stub_size = self.architecture.address_size().unwrap().bytes(); - - let name = b".rdata$.refptr".to_vec(); - let section_id = self.add_section(Vec::new(), name, SectionKind::ReadOnlyData); - let section = self.section_mut(section_id); - section.set_data(vec![0; stub_size as usize], u64::from(stub_size)); - section.relocations = vec![Relocation { - offset: 0, - size: stub_size * 8, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: symbol_id, - addend: 0, - }]; - - let mut name = b".refptr.".to_vec(); - name.extend_from_slice(&self.symbol(symbol_id).name); - let stub_id = self.add_raw_symbol(Symbol { - name, - value: 0, - size: u64::from(stub_size), - kind: SymbolKind::Data, - scope: SymbolScope::Compilation, - weak: false, - section: SymbolSection::Section(section_id), - flags: SymbolFlags::None, - }); - self.stub_symbols.insert(symbol_id, stub_id); - - stub_id - } - - /// Appends linker directives to the `.drectve` section to tell the linker - /// to export all symbols with `SymbolScope::Dynamic`. - /// - /// This must be called after all symbols have been defined. - pub fn add_coff_exports(&mut self, style: CoffExportStyle) { - assert_eq!(self.format, BinaryFormat::Coff); - - let mut directives = vec![]; - for symbol in &self.symbols { - if symbol.scope == SymbolScope::Dynamic { - match style { - CoffExportStyle::Msvc => directives.extend(b" /EXPORT:\""), - CoffExportStyle::Gnu => directives.extend(b" -export:\""), - } - directives.extend(&symbol.name); - directives.extend(b"\""); - if symbol.kind != SymbolKind::Text { - match style { - CoffExportStyle::Msvc => directives.extend(b",DATA"), - CoffExportStyle::Gnu => directives.extend(b",data"), - } - } - } - } - let drectve = self.add_section(vec![], b".drectve".to_vec(), SectionKind::Linker); - self.append_section_data(drectve, &directives, 1); - } - - pub(crate) fn coff_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - let mut writer = writer::Writer::new(buffer); - - // Add section strings to strtab. - let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; - for (index, section) in self.sections.iter().enumerate() { - section_offsets[index].name = writer.add_name(§ion.name); - } - - // Set COMDAT flags. - for comdat in &self.comdats { - let symbol = &self.symbols[comdat.symbol.0]; - let comdat_section = match symbol.section { - SymbolSection::Section(id) => id.0, - _ => { - return Err(Error(format!( - "unsupported COMDAT symbol `{}` section {:?}", - symbol.name().unwrap_or(""), - symbol.section - ))); - } - }; - section_offsets[comdat_section].selection = match comdat.kind { - ComdatKind::NoDuplicates => coff::IMAGE_COMDAT_SELECT_NODUPLICATES, - ComdatKind::Any => coff::IMAGE_COMDAT_SELECT_ANY, - ComdatKind::SameSize => coff::IMAGE_COMDAT_SELECT_SAME_SIZE, - ComdatKind::ExactMatch => coff::IMAGE_COMDAT_SELECT_EXACT_MATCH, - ComdatKind::Largest => coff::IMAGE_COMDAT_SELECT_LARGEST, - ComdatKind::Newest => coff::IMAGE_COMDAT_SELECT_NEWEST, - ComdatKind::Unknown => { - return Err(Error(format!( - "unsupported COMDAT symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - comdat.kind - ))); - } - }; - for id in &comdat.sections { - let section = &self.sections[id.0]; - if section.symbol.is_none() { - return Err(Error(format!( - "missing symbol for COMDAT section `{}`", - section.name().unwrap_or(""), - ))); - } - if id.0 != comdat_section { - section_offsets[id.0].selection = coff::IMAGE_COMDAT_SELECT_ASSOCIATIVE; - section_offsets[id.0].associative_section = comdat_section as u32 + 1; - } - } - } - - // Reserve symbol indices and add symbol strings to strtab. - let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; - for (index, symbol) in self.symbols.iter().enumerate() { - symbol_offsets[index].index = writer.reserve_symbol_index(); - let mut name = &*symbol.name; - match symbol.kind { - SymbolKind::File => { - // Name goes in auxiliary symbol records. - symbol_offsets[index].aux_count = writer.reserve_aux_file_name(&symbol.name); - name = b".file"; - } - SymbolKind::Section if symbol.section.id().is_some() => { - symbol_offsets[index].aux_count = writer.reserve_aux_section(); - } - _ => {} - }; - symbol_offsets[index].name = writer.add_name(name); - } - - // Reserve file ranges. - writer.reserve_file_header(); - writer.reserve_section_headers(self.sections.len() as u16); - for (index, section) in self.sections.iter().enumerate() { - section_offsets[index].offset = writer.reserve_section(section.data.len()); - section_offsets[index].reloc_offset = - writer.reserve_relocations(section.relocations.len()); - } - writer.reserve_symtab_strtab(); - - // Start writing. - writer.write_file_header(writer::FileHeader { - machine: match (self.architecture, self.sub_architecture) { - (Architecture::Arm, None) => coff::IMAGE_FILE_MACHINE_ARMNT, - (Architecture::Aarch64, None) => coff::IMAGE_FILE_MACHINE_ARM64, - (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)) => { - coff::IMAGE_FILE_MACHINE_ARM64EC - } - (Architecture::I386, None) => coff::IMAGE_FILE_MACHINE_I386, - (Architecture::X86_64, None) => coff::IMAGE_FILE_MACHINE_AMD64, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?} with sub-architecture {:?}", - self.architecture, self.sub_architecture - ))); - } - }, - time_date_stamp: 0, - characteristics: match self.flags { - FileFlags::Coff { characteristics } => characteristics, - _ => 0, - }, - })?; - - // Write section headers. - for (index, section) in self.sections.iter().enumerate() { - let mut characteristics = if let SectionFlags::Coff { - characteristics, .. - } = section.flags - { - characteristics - } else { - match section.kind { - SectionKind::Text => { - coff::IMAGE_SCN_CNT_CODE - | coff::IMAGE_SCN_MEM_EXECUTE - | coff::IMAGE_SCN_MEM_READ - } - SectionKind::Data => { - coff::IMAGE_SCN_CNT_INITIALIZED_DATA - | coff::IMAGE_SCN_MEM_READ - | coff::IMAGE_SCN_MEM_WRITE - } - SectionKind::UninitializedData => { - coff::IMAGE_SCN_CNT_UNINITIALIZED_DATA - | coff::IMAGE_SCN_MEM_READ - | coff::IMAGE_SCN_MEM_WRITE - } - SectionKind::ReadOnlyData - | SectionKind::ReadOnlyDataWithRel - | SectionKind::ReadOnlyString => { - coff::IMAGE_SCN_CNT_INITIALIZED_DATA | coff::IMAGE_SCN_MEM_READ - } - SectionKind::Debug | SectionKind::Other | SectionKind::OtherString => { - coff::IMAGE_SCN_CNT_INITIALIZED_DATA - | coff::IMAGE_SCN_MEM_READ - | coff::IMAGE_SCN_MEM_DISCARDABLE - } - SectionKind::Linker => coff::IMAGE_SCN_LNK_INFO | coff::IMAGE_SCN_LNK_REMOVE, - SectionKind::Common - | SectionKind::Tls - | SectionKind::UninitializedTls - | SectionKind::TlsVariables - | SectionKind::Note - | SectionKind::Unknown - | SectionKind::Metadata - | SectionKind::Elf(_) => { - return Err(Error(format!( - "unimplemented section `{}` kind {:?}", - section.name().unwrap_or(""), - section.kind - ))); - } - } - }; - if section_offsets[index].selection != 0 { - characteristics |= coff::IMAGE_SCN_LNK_COMDAT; - }; - if section.relocations.len() > 0xffff { - characteristics |= coff::IMAGE_SCN_LNK_NRELOC_OVFL; - } - characteristics |= match section.align { - 1 => coff::IMAGE_SCN_ALIGN_1BYTES, - 2 => coff::IMAGE_SCN_ALIGN_2BYTES, - 4 => coff::IMAGE_SCN_ALIGN_4BYTES, - 8 => coff::IMAGE_SCN_ALIGN_8BYTES, - 16 => coff::IMAGE_SCN_ALIGN_16BYTES, - 32 => coff::IMAGE_SCN_ALIGN_32BYTES, - 64 => coff::IMAGE_SCN_ALIGN_64BYTES, - 128 => coff::IMAGE_SCN_ALIGN_128BYTES, - 256 => coff::IMAGE_SCN_ALIGN_256BYTES, - 512 => coff::IMAGE_SCN_ALIGN_512BYTES, - 1024 => coff::IMAGE_SCN_ALIGN_1024BYTES, - 2048 => coff::IMAGE_SCN_ALIGN_2048BYTES, - 4096 => coff::IMAGE_SCN_ALIGN_4096BYTES, - 8192 => coff::IMAGE_SCN_ALIGN_8192BYTES, - _ => { - return Err(Error(format!( - "unimplemented section `{}` align {}", - section.name().unwrap_or(""), - section.align - ))); - } - }; - writer.write_section_header(writer::SectionHeader { - name: section_offsets[index].name, - size_of_raw_data: section.size as u32, - pointer_to_raw_data: section_offsets[index].offset, - pointer_to_relocations: section_offsets[index].reloc_offset, - pointer_to_linenumbers: 0, - number_of_relocations: section.relocations.len() as u32, - number_of_linenumbers: 0, - characteristics, - }); - } - - // Write section data and relocations. - for section in &self.sections { - writer.write_section(§ion.data); - - if !section.relocations.is_empty() { - //debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); - writer.write_relocations_count(section.relocations.len()); - for reloc in §ion.relocations { - //assert!(reloc.implicit_addend); - let typ = match self.architecture { - Architecture::I386 => match (reloc.kind, reloc.size, reloc.addend) { - (RelocationKind::Absolute, 16, 0) => coff::IMAGE_REL_I386_DIR16, - (RelocationKind::Relative, 16, 0) => coff::IMAGE_REL_I386_REL16, - (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_I386_DIR32, - (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_I386_DIR32NB, - (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_I386_SECTION, - (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_I386_SECREL, - (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_I386_SECREL7, - (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_I386_REL32, - (RelocationKind::Coff(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::X86_64 => match (reloc.kind, reloc.size, reloc.addend) { - (RelocationKind::Absolute, 64, 0) => coff::IMAGE_REL_AMD64_ADDR64, - (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32, - (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32NB, - (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_AMD64_REL32, - (RelocationKind::Relative, 32, -5) => coff::IMAGE_REL_AMD64_REL32_1, - (RelocationKind::Relative, 32, -6) => coff::IMAGE_REL_AMD64_REL32_2, - (RelocationKind::Relative, 32, -7) => coff::IMAGE_REL_AMD64_REL32_3, - (RelocationKind::Relative, 32, -8) => coff::IMAGE_REL_AMD64_REL32_4, - (RelocationKind::Relative, 32, -9) => coff::IMAGE_REL_AMD64_REL32_5, - (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_AMD64_SECTION, - (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_AMD64_SECREL, - (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_AMD64_SECREL7, - (RelocationKind::Coff(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Arm => match (reloc.kind, reloc.size, reloc.addend) { - (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_ARM_ADDR32, - (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_ARM_ADDR32NB, - (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_ARM_REL32, - (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_ARM_SECTION, - (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_ARM_SECREL, - (RelocationKind::Coff(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Aarch64 => match (reloc.kind, reloc.size, reloc.addend) { - (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_ARM64_ADDR32, - (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_ARM64_ADDR32NB, - (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_ARM64_SECTION, - (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_ARM64_SECREL, - (RelocationKind::Absolute, 64, 0) => coff::IMAGE_REL_ARM64_ADDR64, - (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_ARM64_REL32, - (RelocationKind::Coff(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", - self.architecture - ))); - } - }; - writer.write_relocation(writer::Relocation { - virtual_address: reloc.offset as u32, - symbol: symbol_offsets[reloc.symbol.0].index, - typ, - }); - } - } - } - - // Write symbols. - for (index, symbol) in self.symbols.iter().enumerate() { - let section_number = match symbol.section { - SymbolSection::None => { - debug_assert_eq!(symbol.kind, SymbolKind::File); - coff::IMAGE_SYM_DEBUG as u16 - } - SymbolSection::Undefined => coff::IMAGE_SYM_UNDEFINED as u16, - SymbolSection::Absolute => coff::IMAGE_SYM_ABSOLUTE as u16, - SymbolSection::Common => coff::IMAGE_SYM_UNDEFINED as u16, - SymbolSection::Section(id) => id.0 as u16 + 1, - }; - let typ = if symbol.kind == SymbolKind::Text { - coff::IMAGE_SYM_DTYPE_FUNCTION << coff::IMAGE_SYM_DTYPE_SHIFT - } else { - coff::IMAGE_SYM_TYPE_NULL - }; - let storage_class = match symbol.kind { - SymbolKind::File => coff::IMAGE_SYM_CLASS_FILE, - SymbolKind::Section => { - if symbol.section.id().is_some() { - coff::IMAGE_SYM_CLASS_STATIC - } else { - coff::IMAGE_SYM_CLASS_SECTION - } - } - SymbolKind::Label => coff::IMAGE_SYM_CLASS_LABEL, - SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => { - match symbol.section { - SymbolSection::None => { - return Err(Error(format!( - "missing section for symbol `{}`", - symbol.name().unwrap_or("") - ))); - } - SymbolSection::Undefined | SymbolSection::Common => { - coff::IMAGE_SYM_CLASS_EXTERNAL - } - SymbolSection::Absolute | SymbolSection::Section(_) => { - match symbol.scope { - // TODO: does this need aux symbol records too? - _ if symbol.weak => coff::IMAGE_SYM_CLASS_WEAK_EXTERNAL, - SymbolScope::Unknown => { - return Err(Error(format!( - "unimplemented symbol `{}` scope {:?}", - symbol.name().unwrap_or(""), - symbol.scope - ))); - } - SymbolScope::Compilation => coff::IMAGE_SYM_CLASS_STATIC, - SymbolScope::Linkage | SymbolScope::Dynamic => { - coff::IMAGE_SYM_CLASS_EXTERNAL - } - } - } - } - } - SymbolKind::Unknown | SymbolKind::Null => { - return Err(Error(format!( - "unimplemented symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - symbol.kind - ))); - } - }; - let number_of_aux_symbols = symbol_offsets[index].aux_count; - let value = if symbol.section == SymbolSection::Common { - symbol.size as u32 - } else { - symbol.value as u32 - }; - writer.write_symbol(writer::Symbol { - name: symbol_offsets[index].name, - value, - section_number, - typ, - storage_class, - number_of_aux_symbols, - }); - - // Write auxiliary symbols. - match symbol.kind { - SymbolKind::File => { - writer.write_aux_file_name(&symbol.name, number_of_aux_symbols); - } - SymbolKind::Section if symbol.section.id().is_some() => { - debug_assert_eq!(number_of_aux_symbols, 1); - let section_index = symbol.section.id().unwrap().0; - let section = &self.sections[section_index]; - writer.write_aux_section(writer::AuxSymbolSection { - length: section.size as u32, - number_of_relocations: section.relocations.len() as u32, - number_of_linenumbers: 0, - check_sum: checksum(section.data()), - number: section_offsets[section_index].associative_section, - selection: section_offsets[section_index].selection, - }); - } - _ => { - debug_assert_eq!(number_of_aux_symbols, 0); - } - } - } - - writer.write_strtab(); - - debug_assert_eq!(writer.reserved_len(), writer.len()); - - Ok(()) - } -} - -// JamCRC -fn checksum(data: &[u8]) -> u32 { - let mut hasher = crc32fast::Hasher::new_with_initial(0xffff_ffff); - hasher.update(data); - !hasher.finalize() -} diff --git a/vendor/object/src/write/coff/writer.rs b/vendor/object/src/write/coff/writer.rs deleted file mode 100644 index 8c7ada3..0000000 --- a/vendor/object/src/write/coff/writer.rs +++ /dev/null @@ -1,518 +0,0 @@ -//! Helper for writing COFF files. -use alloc::string::String; -use alloc::vec::Vec; -use core::mem; - -use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32}; -use crate::pe; -use crate::write::string::{StringId, StringTable}; -use crate::write::util; -use crate::write::{Error, Result, WritableBuffer}; - -/// A helper for writing COFF files. -/// -/// Writing uses a two phase approach. The first phase builds up all of the information -/// that may need to be known ahead of time: -/// - build string table -/// - reserve section indices -/// - reserve symbol indices -/// - reserve file ranges for headers and sections -/// -/// Some of the information has ordering requirements. For example, strings must be added -/// to the string table before reserving the file range for the string table. There are debug -/// asserts to check some of these requirements. -/// -/// The second phase writes everything out in order. Thus the caller must ensure writing -/// is in the same order that file ranges were reserved. There are debug asserts to assist -/// with checking this. -#[allow(missing_debug_implementations)] -pub struct Writer<'a> { - buffer: &'a mut dyn WritableBuffer, - len: usize, - - section_num: u16, - - symtab_offset: u32, - symtab_num: u32, - - strtab: StringTable<'a>, - strtab_len: usize, - strtab_offset: u32, - strtab_data: Vec, -} - -impl<'a> Writer<'a> { - /// Create a new `Writer`. - pub fn new(buffer: &'a mut dyn WritableBuffer) -> Self { - Writer { - buffer, - len: 0, - - section_num: 0, - - symtab_offset: 0, - symtab_num: 0, - - strtab: StringTable::default(), - strtab_len: 0, - strtab_offset: 0, - strtab_data: Vec::new(), - } - } - - /// Return the current file length that has been reserved. - pub fn reserved_len(&self) -> usize { - self.len - } - - /// Return the current file length that has been written. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.buffer.len() - } - - /// Reserve a file range with the given size and starting alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve(&mut self, len: usize, align_start: usize) -> u32 { - if align_start > 1 { - self.len = util::align(self.len, align_start); - } - let offset = self.len; - self.len += len; - offset as u32 - } - - /// Write alignment padding bytes. - pub fn write_align(&mut self, align_start: usize) { - if align_start > 1 { - util::write_align(self.buffer, align_start); - } - } - - /// Write data. - pub fn write(&mut self, data: &[u8]) { - self.buffer.write_bytes(data); - } - - /// Reserve the file range up to the given file offset. - pub fn reserve_until(&mut self, offset: usize) { - debug_assert!(self.len <= offset); - self.len = offset; - } - - /// Write padding up to the given file offset. - pub fn pad_until(&mut self, offset: usize) { - debug_assert!(self.buffer.len() <= offset); - self.buffer.resize(offset); - } - - /// Reserve the range for the file header. - /// - /// This must be at the start of the file. - pub fn reserve_file_header(&mut self) { - debug_assert_eq!(self.len, 0); - self.reserve(mem::size_of::(), 1); - } - - /// Write the file header. - /// - /// This must be at the start of the file. - /// - /// Fields that can be derived from known information are automatically set by this function. - pub fn write_file_header(&mut self, header: FileHeader) -> Result<()> { - debug_assert_eq!(self.buffer.len(), 0); - - // Start writing. - self.buffer - .reserve(self.len) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - // Write file header. - let header = pe::ImageFileHeader { - machine: U16::new(LE, header.machine), - number_of_sections: U16::new(LE, self.section_num), - time_date_stamp: U32::new(LE, header.time_date_stamp), - pointer_to_symbol_table: U32::new(LE, self.symtab_offset), - number_of_symbols: U32::new(LE, self.symtab_num), - size_of_optional_header: U16::default(), - characteristics: U16::new(LE, header.characteristics), - }; - self.buffer.write(&header); - - Ok(()) - } - - /// Reserve the range for the section headers. - pub fn reserve_section_headers(&mut self, section_num: u16) { - debug_assert_eq!(self.section_num, 0); - self.section_num = section_num; - self.reserve( - section_num as usize * mem::size_of::(), - 1, - ); - } - - /// Write a section header. - pub fn write_section_header(&mut self, section: SectionHeader) { - let mut coff_section = pe::ImageSectionHeader { - name: [0; 8], - virtual_size: U32::default(), - virtual_address: U32::default(), - size_of_raw_data: U32::new(LE, section.size_of_raw_data), - pointer_to_raw_data: U32::new(LE, section.pointer_to_raw_data), - pointer_to_relocations: U32::new(LE, section.pointer_to_relocations), - pointer_to_linenumbers: U32::new(LE, section.pointer_to_linenumbers), - number_of_relocations: if section.number_of_relocations > 0xffff { - U16::new(LE, 0xffff) - } else { - U16::new(LE, section.number_of_relocations as u16) - }, - number_of_linenumbers: U16::default(), - characteristics: U32::new(LE, section.characteristics), - }; - match section.name { - Name::Short(name) => coff_section.name = name, - Name::Long(str_id) => { - let mut str_offset = self.strtab.get_offset(str_id); - if str_offset <= 9_999_999 { - let mut name = [0; 7]; - let mut len = 0; - if str_offset == 0 { - name[6] = b'0'; - len = 1; - } else { - while str_offset != 0 { - let rem = (str_offset % 10) as u8; - str_offset /= 10; - name[6 - len] = b'0' + rem; - len += 1; - } - } - coff_section.name = [0; 8]; - coff_section.name[0] = b'/'; - coff_section.name[1..][..len].copy_from_slice(&name[7 - len..]); - } else { - debug_assert!(str_offset as u64 <= 0xf_ffff_ffff); - coff_section.name[0] = b'/'; - coff_section.name[1] = b'/'; - for i in 0..6 { - let rem = (str_offset % 64) as u8; - str_offset /= 64; - let c = match rem { - 0..=25 => b'A' + rem, - 26..=51 => b'a' + rem - 26, - 52..=61 => b'0' + rem - 52, - 62 => b'+', - 63 => b'/', - _ => unreachable!(), - }; - coff_section.name[7 - i] = c; - } - } - } - } - self.buffer.write(&coff_section); - } - - /// Reserve the range for the section data. - /// - /// Returns the aligned offset of the start of the range. - /// Does nothing and returns 0 if the length is zero. - pub fn reserve_section(&mut self, len: usize) -> u32 { - if len == 0 { - return 0; - } - // TODO: not sure what alignment is required here, but this seems to match LLVM - self.reserve(len, 4) - } - - /// Write the alignment bytes prior to section data. - /// - /// This is unneeded if you are using `write_section` or `write_section_zeroes` - /// for the data. - pub fn write_section_align(&mut self) { - util::write_align(self.buffer, 4); - } - - /// Write the section data. - /// - /// Writes alignment bytes prior to the data. - /// Does nothing if the data is empty. - pub fn write_section(&mut self, data: &[u8]) { - if data.is_empty() { - return; - } - self.write_section_align(); - self.buffer.write_bytes(data); - } - - /// Write the section data using zero bytes. - /// - /// Writes alignment bytes prior to the data. - /// Does nothing if the length is zero. - pub fn write_section_zeroes(&mut self, len: usize) { - if len == 0 { - return; - } - self.write_section_align(); - self.buffer.resize(self.buffer.len() + len); - } - - /// Reserve a file range for the given number of relocations. - /// - /// This will automatically reserve an extra relocation if there are more than 0xffff. - /// - /// Returns the offset of the range. - /// Does nothing and returns 0 if the count is zero. - pub fn reserve_relocations(&mut self, mut count: usize) -> u32 { - if count == 0 { - return 0; - } - if count > 0xffff { - count += 1; - } - self.reserve(count * mem::size_of::(), 1) - } - - /// Write a relocation containing the count if required. - /// - /// This should be called before writing the first relocation for a section. - pub fn write_relocations_count(&mut self, count: usize) { - if count > 0xffff { - let coff_relocation = pe::ImageRelocation { - virtual_address: U32Bytes::new(LE, count as u32 + 1), - symbol_table_index: U32Bytes::new(LE, 0), - typ: U16Bytes::new(LE, 0), - }; - self.buffer.write(&coff_relocation); - } - } - - /// Write a relocation. - pub fn write_relocation(&mut self, reloc: Relocation) { - let coff_relocation = pe::ImageRelocation { - virtual_address: U32Bytes::new(LE, reloc.virtual_address), - symbol_table_index: U32Bytes::new(LE, reloc.symbol), - typ: U16Bytes::new(LE, reloc.typ), - }; - self.buffer.write(&coff_relocation); - } - - /// Reserve a symbol table entry. - /// - /// This must be called before [`Self::reserve_symtab_strtab`]. - pub fn reserve_symbol_index(&mut self) -> u32 { - debug_assert_eq!(self.symtab_offset, 0); - let index = self.symtab_num; - self.symtab_num += 1; - index - } - - /// Reserve a number of symbol table entries. - pub fn reserve_symbol_indices(&mut self, count: u32) { - debug_assert_eq!(self.symtab_offset, 0); - self.symtab_num += count; - } - - /// Write a symbol table entry. - pub fn write_symbol(&mut self, symbol: Symbol) { - let mut coff_symbol = pe::ImageSymbol { - name: [0; 8], - value: U32Bytes::new(LE, symbol.value), - section_number: U16Bytes::new(LE, symbol.section_number), - typ: U16Bytes::new(LE, symbol.typ), - storage_class: symbol.storage_class, - number_of_aux_symbols: symbol.number_of_aux_symbols, - }; - match symbol.name { - Name::Short(name) => coff_symbol.name = name, - Name::Long(str_id) => { - let str_offset = self.strtab.get_offset(str_id); - coff_symbol.name[4..8].copy_from_slice(&u32::to_le_bytes(str_offset as u32)); - } - } - self.buffer.write(&coff_symbol); - } - - /// Reserve auxiliary symbols for a file name. - /// - /// Returns the number of auxiliary symbols required. - /// - /// This must be called before [`Self::reserve_symtab_strtab`]. - pub fn reserve_aux_file_name(&mut self, name: &[u8]) -> u8 { - debug_assert_eq!(self.symtab_offset, 0); - let aux_count = (name.len() + pe::IMAGE_SIZEOF_SYMBOL - 1) / pe::IMAGE_SIZEOF_SYMBOL; - self.symtab_num += aux_count as u32; - aux_count as u8 - } - - /// Write auxiliary symbols for a file name. - pub fn write_aux_file_name(&mut self, name: &[u8], aux_count: u8) { - let aux_len = aux_count as usize * pe::IMAGE_SIZEOF_SYMBOL; - debug_assert!(aux_len >= name.len()); - let old_len = self.buffer.len(); - self.buffer.write_bytes(name); - self.buffer.resize(old_len + aux_len); - } - - /// Reserve an auxiliary symbol for a section. - /// - /// Returns the number of auxiliary symbols required. - /// - /// This must be called before [`Self::reserve_symtab_strtab`]. - pub fn reserve_aux_section(&mut self) -> u8 { - debug_assert_eq!(self.symtab_offset, 0); - self.symtab_num += 1; - 1 - } - - /// Write an auxiliary symbol for a section. - pub fn write_aux_section(&mut self, section: AuxSymbolSection) { - let aux = pe::ImageAuxSymbolSection { - length: U32Bytes::new(LE, section.length), - number_of_relocations: if section.number_of_relocations > 0xffff { - U16Bytes::new(LE, 0xffff) - } else { - U16Bytes::new(LE, section.number_of_relocations as u16) - }, - number_of_linenumbers: U16Bytes::new(LE, section.number_of_linenumbers), - check_sum: U32Bytes::new(LE, section.check_sum), - number: U16Bytes::new(LE, section.number as u16), - selection: section.selection, - reserved: 0, - high_number: U16Bytes::new(LE, (section.number >> 16) as u16), - }; - self.buffer.write(&aux); - } - - /// Return the number of reserved symbol table entries. - pub fn symbol_count(&self) -> u32 { - self.symtab_num - } - - /// Add a string to the string table. - /// - /// This must be called before [`Self::reserve_symtab_strtab`]. - pub fn add_string(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.strtab_offset, 0); - self.strtab.add(name) - } - - /// Add a section or symbol name to the string table if required. - /// - /// This must be called before [`Self::reserve_symtab_strtab`]. - pub fn add_name(&mut self, name: &'a [u8]) -> Name { - if name.len() > 8 { - Name::Long(self.add_string(name)) - } else { - let mut short_name = [0; 8]; - short_name[..name.len()].copy_from_slice(name); - Name::Short(short_name) - } - } - - /// Reserve the range for the symbol table and string table. - /// - /// This must be called after functions that reserve symbol - /// indices or add strings. - pub fn reserve_symtab_strtab(&mut self) { - debug_assert_eq!(self.symtab_offset, 0); - self.symtab_offset = self.reserve(self.symtab_num as usize * pe::IMAGE_SIZEOF_SYMBOL, 1); - - debug_assert_eq!(self.strtab_offset, 0); - // First 4 bytes of strtab are the length. - self.strtab.write(4, &mut self.strtab_data); - self.strtab_len = self.strtab_data.len() + 4; - self.strtab_offset = self.reserve(self.strtab_len, 1); - } - - /// Write the string table. - pub fn write_strtab(&mut self) { - debug_assert_eq!(self.strtab_offset, self.buffer.len() as u32); - self.buffer - .write_bytes(&u32::to_le_bytes(self.strtab_len as u32)); - self.buffer.write_bytes(&self.strtab_data); - } -} - -/// Shortened and native endian version of [`pe::ImageFileHeader`]. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone)] -pub struct FileHeader { - pub machine: u16, - pub time_date_stamp: u32, - pub characteristics: u16, -} - -/// A section or symbol name. -#[derive(Debug, Clone, Copy)] -pub enum Name { - /// An inline name. - Short([u8; 8]), - /// An id of a string table entry. - Long(StringId), -} - -impl Default for Name { - fn default() -> Name { - Name::Short([0; 8]) - } -} - -// From isn't useful. -#[allow(clippy::from_over_into)] -impl<'a> Into for &'a [u8; 8] { - fn into(self) -> Name { - Name::Short(*self) - } -} - -/// Native endian version of [`pe::ImageSectionHeader`]. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone)] -pub struct SectionHeader { - pub name: Name, - pub size_of_raw_data: u32, - pub pointer_to_raw_data: u32, - pub pointer_to_relocations: u32, - pub pointer_to_linenumbers: u32, - /// This will automatically be clamped if there are more than 0xffff. - pub number_of_relocations: u32, - pub number_of_linenumbers: u16, - pub characteristics: u32, -} - -/// Native endian version of [`pe::ImageSymbol`]. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone)] -pub struct Symbol { - pub name: Name, - pub value: u32, - pub section_number: u16, - pub typ: u16, - pub storage_class: u8, - pub number_of_aux_symbols: u8, -} - -/// Native endian version of [`pe::ImageAuxSymbolSection`]. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone)] -pub struct AuxSymbolSection { - pub length: u32, - /// This will automatically be clamped if there are more than 0xffff. - pub number_of_relocations: u32, - pub number_of_linenumbers: u16, - pub check_sum: u32, - pub number: u32, - pub selection: u8, -} - -/// Native endian version of [`pe::ImageRelocation`]. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone)] -pub struct Relocation { - pub virtual_address: u32, - pub symbol: u32, - pub typ: u16, -} diff --git a/vendor/object/src/write/elf/mod.rs b/vendor/object/src/write/elf/mod.rs deleted file mode 100644 index 3a4f371..0000000 --- a/vendor/object/src/write/elf/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Support for writing ELF files. -//! -//! Provides [`Writer`] for low level writing of ELF files. -//! This is also used to provide ELF support for [`write::Object`](crate::write::Object). - -mod object; - -mod writer; -pub use writer::*; diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs deleted file mode 100644 index 5d7a93e..0000000 --- a/vendor/object/src/write/elf/object.rs +++ /dev/null @@ -1,907 +0,0 @@ -use alloc::vec::Vec; - -use crate::write::elf::writer::*; -use crate::write::string::StringId; -use crate::write::*; -use crate::AddressSize; -use crate::{elf, pod}; - -#[derive(Clone, Copy)] -struct ComdatOffsets { - offset: usize, - str_id: StringId, -} - -#[derive(Clone, Copy)] -struct SectionOffsets { - index: SectionIndex, - offset: usize, - str_id: StringId, - reloc_offset: usize, - reloc_str_id: Option, -} - -#[derive(Default, Clone, Copy)] -struct SymbolOffsets { - index: SymbolIndex, - str_id: Option, -} - -// Public methods. -impl<'a> Object<'a> { - /// Add a property with a u32 value to the ELF ".note.gnu.property" section. - /// - /// Requires `feature = "elf"`. - pub fn add_elf_gnu_property_u32(&mut self, property: u32, value: u32) { - if self.format != BinaryFormat::Elf { - return; - } - - let align = if self.elf_is_64() { 8 } else { 4 }; - let mut data = Vec::with_capacity(32); - let n_name = b"GNU\0"; - data.extend_from_slice(pod::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(self.endian, n_name.len() as u32), - n_descsz: U32::new(self.endian, util::align(3 * 4, align) as u32), - n_type: U32::new(self.endian, elf::NT_GNU_PROPERTY_TYPE_0), - })); - data.extend_from_slice(n_name); - // This happens to already be aligned correctly. - debug_assert_eq!(util::align(data.len(), align), data.len()); - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, property))); - // Value size - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, 4))); - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, value))); - util::write_align(&mut data, align); - - let section = self.section_id(StandardSection::GnuProperty); - self.append_section_data(section, &data, align as u64); - } -} - -// Private methods. -impl<'a> Object<'a> { - pub(crate) fn elf_section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match section { - StandardSection::Text => (&[], &b".text"[..], SectionKind::Text, SectionFlags::None), - StandardSection::Data => (&[], &b".data"[..], SectionKind::Data, SectionFlags::None), - StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => ( - &[], - &b".rodata"[..], - SectionKind::ReadOnlyData, - SectionFlags::None, - ), - StandardSection::ReadOnlyDataWithRel => ( - &[], - b".data.rel.ro", - SectionKind::ReadOnlyDataWithRel, - SectionFlags::None, - ), - StandardSection::UninitializedData => ( - &[], - &b".bss"[..], - SectionKind::UninitializedData, - SectionFlags::None, - ), - StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls, SectionFlags::None), - StandardSection::UninitializedTls => ( - &[], - &b".tbss"[..], - SectionKind::UninitializedTls, - SectionFlags::None, - ), - StandardSection::TlsVariables => { - // Unsupported section. - (&[], &[], SectionKind::TlsVariables, SectionFlags::None) - } - StandardSection::Common => { - // Unsupported section. - (&[], &[], SectionKind::Common, SectionFlags::None) - } - StandardSection::GnuProperty => ( - &[], - &b".note.gnu.property"[..], - SectionKind::Note, - SectionFlags::Elf { - sh_flags: u64::from(elf::SHF_ALLOC), - }, - ), - } - } - - pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec { - let mut name = section.to_vec(); - name.push(b'.'); - name.extend_from_slice(value); - name - } - - fn elf_has_relocation_addend(&self) -> Result { - Ok(match self.architecture { - Architecture::Aarch64 => true, - Architecture::Aarch64_Ilp32 => true, - Architecture::Arm => false, - Architecture::Avr => true, - Architecture::Bpf => false, - Architecture::Csky => true, - Architecture::I386 => false, - Architecture::X86_64 => true, - Architecture::X86_64_X32 => true, - Architecture::Hexagon => true, - Architecture::LoongArch64 => true, - Architecture::Mips => false, - Architecture::Mips64 => true, - Architecture::Msp430 => true, - Architecture::PowerPc => true, - Architecture::PowerPc64 => true, - Architecture::Riscv64 => true, - Architecture::Riscv32 => true, - Architecture::S390x => true, - Architecture::Sbf => false, - Architecture::Sharc => true, - Architecture::Sparc64 => true, - Architecture::Xtensa => true, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", - self.architecture - ))); - } - }) - } - - pub(crate) fn elf_fixup_relocation(&mut self, relocation: &mut Relocation) -> Result { - // Determine whether the addend is stored in the relocation or the data. - if self.elf_has_relocation_addend()? { - Ok(0) - } else { - let constant = relocation.addend; - relocation.addend = 0; - Ok(constant) - } - } - - pub(crate) fn elf_is_64(&self) -> bool { - match self.architecture.address_size().unwrap() { - AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false, - AddressSize::U64 => true, - } - } - - pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - // Create reloc section header names so we can reference them. - let is_rela = self.elf_has_relocation_addend()?; - let reloc_names: Vec<_> = self - .sections - .iter() - .map(|section| { - let mut reloc_name = Vec::with_capacity( - if is_rela { ".rela".len() } else { ".rel".len() } + section.name.len(), - ); - if !section.relocations.is_empty() { - reloc_name.extend_from_slice(if is_rela { - &b".rela"[..] - } else { - &b".rel"[..] - }); - reloc_name.extend_from_slice(§ion.name); - } - reloc_name - }) - .collect(); - - // Start calculating offsets of everything. - let mut writer = Writer::new(self.endian, self.elf_is_64(), buffer); - writer.reserve_file_header(); - - // Calculate size of section data. - let mut comdat_offsets = Vec::with_capacity(self.comdats.len()); - for comdat in &self.comdats { - if comdat.kind != ComdatKind::Any { - return Err(Error(format!( - "unsupported COMDAT symbol `{}` kind {:?}", - self.symbols[comdat.symbol.0].name().unwrap_or(""), - comdat.kind - ))); - } - - writer.reserve_section_index(); - let offset = writer.reserve_comdat(comdat.sections.len()); - let str_id = writer.add_section_name(b".group"); - comdat_offsets.push(ComdatOffsets { offset, str_id }); - } - let mut section_offsets = Vec::with_capacity(self.sections.len()); - for (section, reloc_name) in self.sections.iter().zip(reloc_names.iter()) { - let index = writer.reserve_section_index(); - let offset = writer.reserve(section.data.len(), section.align as usize); - let str_id = writer.add_section_name(§ion.name); - let mut reloc_str_id = None; - if !section.relocations.is_empty() { - writer.reserve_section_index(); - reloc_str_id = Some(writer.add_section_name(reloc_name)); - } - section_offsets.push(SectionOffsets { - index, - offset, - str_id, - // Relocation data is reserved later. - reloc_offset: 0, - reloc_str_id, - }); - } - - // Calculate index of symbols and add symbol strings to strtab. - let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; - writer.reserve_null_symbol_index(); - // Local symbols must come before global. - for (index, symbol) in self.symbols.iter().enumerate() { - if symbol.is_local() { - let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); - symbol_offsets[index].index = writer.reserve_symbol_index(section_index); - } - } - let symtab_num_local = writer.symbol_count(); - for (index, symbol) in self.symbols.iter().enumerate() { - if !symbol.is_local() { - let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); - symbol_offsets[index].index = writer.reserve_symbol_index(section_index); - } - } - for (index, symbol) in self.symbols.iter().enumerate() { - if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() { - symbol_offsets[index].str_id = Some(writer.add_string(&symbol.name)); - } - } - - // Calculate size of symbols. - writer.reserve_symtab_section_index(); - writer.reserve_symtab(); - if writer.symtab_shndx_needed() { - writer.reserve_symtab_shndx_section_index(); - } - writer.reserve_symtab_shndx(); - writer.reserve_strtab_section_index(); - writer.reserve_strtab(); - - // Calculate size of relocations. - for (index, section) in self.sections.iter().enumerate() { - let count = section.relocations.len(); - if count != 0 { - section_offsets[index].reloc_offset = writer.reserve_relocations(count, is_rela); - } - } - - // Calculate size of section headers. - writer.reserve_shstrtab_section_index(); - writer.reserve_shstrtab(); - writer.reserve_section_headers(); - - // Start writing. - let e_type = elf::ET_REL; - let e_machine = match (self.architecture, self.sub_architecture) { - (Architecture::Aarch64, None) => elf::EM_AARCH64, - (Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64, - (Architecture::Arm, None) => elf::EM_ARM, - (Architecture::Avr, None) => elf::EM_AVR, - (Architecture::Bpf, None) => elf::EM_BPF, - (Architecture::Csky, None) => elf::EM_CSKY, - (Architecture::I386, None) => elf::EM_386, - (Architecture::X86_64, None) => elf::EM_X86_64, - (Architecture::X86_64_X32, None) => elf::EM_X86_64, - (Architecture::Hexagon, None) => elf::EM_HEXAGON, - (Architecture::LoongArch64, None) => elf::EM_LOONGARCH, - (Architecture::Mips, None) => elf::EM_MIPS, - (Architecture::Mips64, None) => elf::EM_MIPS, - (Architecture::Msp430, None) => elf::EM_MSP430, - (Architecture::PowerPc, None) => elf::EM_PPC, - (Architecture::PowerPc64, None) => elf::EM_PPC64, - (Architecture::Riscv32, None) => elf::EM_RISCV, - (Architecture::Riscv64, None) => elf::EM_RISCV, - (Architecture::S390x, None) => elf::EM_S390, - (Architecture::Sbf, None) => elf::EM_SBF, - (Architecture::Sharc, None) => elf::EM_SHARC, - (Architecture::Sparc64, None) => elf::EM_SPARCV9, - (Architecture::Xtensa, None) => elf::EM_XTENSA, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?} with sub-architecture {:?}", - self.architecture, self.sub_architecture - ))); - } - }; - let (os_abi, abi_version, e_flags) = if let FileFlags::Elf { - os_abi, - abi_version, - e_flags, - } = self.flags - { - (os_abi, abi_version, e_flags) - } else { - (elf::ELFOSABI_NONE, 0, 0) - }; - writer.write_file_header(&FileHeader { - os_abi, - abi_version, - e_type, - e_machine, - e_entry: 0, - e_flags, - })?; - - // Write section data. - for comdat in &self.comdats { - writer.write_comdat_header(); - for section in &comdat.sections { - writer.write_comdat_entry(section_offsets[section.0].index); - } - } - for (index, section) in self.sections.iter().enumerate() { - writer.write_align(section.align as usize); - debug_assert_eq!(section_offsets[index].offset, writer.len()); - writer.write(§ion.data); - } - - // Write symbols. - writer.write_null_symbol(); - let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> { - let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags { - st_info - } else { - let st_type = match symbol.kind { - SymbolKind::Null => elf::STT_NOTYPE, - SymbolKind::Text => { - if symbol.is_undefined() { - elf::STT_NOTYPE - } else { - elf::STT_FUNC - } - } - SymbolKind::Data => { - if symbol.is_undefined() { - elf::STT_NOTYPE - } else if symbol.is_common() { - elf::STT_COMMON - } else { - elf::STT_OBJECT - } - } - SymbolKind::Section => elf::STT_SECTION, - SymbolKind::File => elf::STT_FILE, - SymbolKind::Tls => elf::STT_TLS, - SymbolKind::Label => elf::STT_NOTYPE, - SymbolKind::Unknown => { - if symbol.is_undefined() { - elf::STT_NOTYPE - } else { - return Err(Error(format!( - "unimplemented symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - symbol.kind - ))); - } - } - }; - let st_bind = if symbol.weak { - elf::STB_WEAK - } else if symbol.is_undefined() { - elf::STB_GLOBAL - } else if symbol.is_local() { - elf::STB_LOCAL - } else { - elf::STB_GLOBAL - }; - (st_bind << 4) + st_type - }; - let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags { - st_other - } else if symbol.scope == SymbolScope::Linkage { - elf::STV_HIDDEN - } else { - elf::STV_DEFAULT - }; - let (st_shndx, section) = match symbol.section { - SymbolSection::None => { - debug_assert_eq!(symbol.kind, SymbolKind::File); - (elf::SHN_ABS, None) - } - SymbolSection::Undefined => (elf::SHN_UNDEF, None), - SymbolSection::Absolute => (elf::SHN_ABS, None), - SymbolSection::Common => (elf::SHN_COMMON, None), - SymbolSection::Section(id) => (0, Some(section_offsets[id.0].index)), - }; - writer.write_symbol(&Sym { - name: symbol_offsets[index].str_id, - section, - st_info, - st_other, - st_shndx, - st_value: symbol.value, - st_size: symbol.size, - }); - Ok(()) - }; - for (index, symbol) in self.symbols.iter().enumerate() { - if symbol.is_local() { - write_symbol(index, symbol)?; - } - } - for (index, symbol) in self.symbols.iter().enumerate() { - if !symbol.is_local() { - write_symbol(index, symbol)?; - } - } - writer.write_symtab_shndx(); - writer.write_strtab(); - - // Write relocations. - for (index, section) in self.sections.iter().enumerate() { - if !section.relocations.is_empty() { - writer.write_align_relocation(); - debug_assert_eq!(section_offsets[index].reloc_offset, writer.len()); - for reloc in §ion.relocations { - let r_type = match self.architecture { - Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { - elf::R_AARCH64_ABS64 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_AARCH64_ABS32 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { - elf::R_AARCH64_ABS16 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 64) => { - elf::R_AARCH64_PREL64 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_AARCH64_PREL32 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 16) => { - elf::R_AARCH64_PREL16 - } - (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26) - | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => { - elf::R_AARCH64_CALL26 - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Aarch64_Ilp32 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_AARCH64_P32_ABS32 - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!( - "unimplemented relocation {:?}", - reloc - ))); - } - } - } - Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Avr => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_AVR_32, - (RelocationKind::Absolute, _, 16) => elf::R_AVR_16, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Bpf => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 64) => elf::R_BPF_64_64, - (RelocationKind::Absolute, _, 32) => elf::R_BPF_64_32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Csky => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_CKCORE_ADDR32, - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_CKCORE_PCREL32 - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::I386 => match (reloc.kind, reloc.size) { - (RelocationKind::Absolute, 32) => elf::R_386_32, - (RelocationKind::Relative, 32) => elf::R_386_PC32, - (RelocationKind::Got, 32) => elf::R_386_GOT32, - (RelocationKind::PltRelative, 32) => elf::R_386_PLT32, - (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF, - (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC, - (RelocationKind::Absolute, 16) => elf::R_386_16, - (RelocationKind::Relative, 16) => elf::R_386_PC16, - (RelocationKind::Absolute, 8) => elf::R_386_8, - (RelocationKind::Relative, 8) => elf::R_386_PC8, - (RelocationKind::Elf(x), _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::X86_64 | Architecture::X86_64_X32 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { - elf::R_X86_64_64 - } - (RelocationKind::Relative, RelocationEncoding::X86Branch, 32) => { - elf::R_X86_64_PLT32 - } - (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32, - (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32, - (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32, - (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL, - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_X86_64_32 - } - (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => { - elf::R_X86_64_32S - } - (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16, - (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16, - (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8, - (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!( - "unimplemented relocation {:?}", - reloc - ))); - } - } - } - Architecture::Hexagon => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_HEX_32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) - { - (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, - (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, - (RelocationKind::Relative, _, 32) => elf::R_LARCH_32_PCREL, - (RelocationKind::Relative, _, 64) => elf::R_LARCH_64_PCREL, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 16) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 16, - ) => elf::R_LARCH_B16, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 21) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 21, - ) => elf::R_LARCH_B21, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 26) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 26, - ) => elf::R_LARCH_B26, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Mips | Architecture::Mips64 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16, - (RelocationKind::Absolute, _, 32) => elf::R_MIPS_32, - (RelocationKind::Absolute, _, 64) => elf::R_MIPS_64, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!( - "unimplemented relocation {:?}", - reloc - ))); - } - } - } - Architecture::Msp430 => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_MSP430_32, - (RelocationKind::Absolute, _, 16) => elf::R_MSP430_16_BYTE, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::PowerPc => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_PPC_ADDR32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::PowerPc64 => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_PPC64_ADDR32, - (RelocationKind::Absolute, _, 64) => elf::R_PPC64_ADDR64, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Riscv32 | Architecture::Riscv64 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_RISCV_32, - (RelocationKind::Absolute, _, 64) => elf::R_RISCV_64, - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_RISCV_32_PCREL - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!( - "unimplemented relocation {:?}", - reloc - ))); - } - } - } - Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => { - elf::R_390_8 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { - elf::R_390_16 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_390_32 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { - elf::R_390_64 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 16) => { - elf::R_390_PC16 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_390_PC32 - } - (RelocationKind::Relative, RelocationEncoding::Generic, 64) => { - elf::R_390_PC64 - } - (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => { - elf::R_390_PC16DBL - } - (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => { - elf::R_390_PC32DBL - } - (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => { - elf::R_390_PLT16DBL - } - (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => { - elf::R_390_PLT32DBL - } - (RelocationKind::Got, RelocationEncoding::Generic, 16) => { - elf::R_390_GOT16 - } - (RelocationKind::Got, RelocationEncoding::Generic, 32) => { - elf::R_390_GOT32 - } - (RelocationKind::Got, RelocationEncoding::Generic, 64) => { - elf::R_390_GOT64 - } - (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => { - elf::R_390_GOTENT - } - (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => { - elf::R_390_GOTOFF16 - } - (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => { - elf::R_390_GOTOFF32 - } - (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => { - elf::R_390_GOTOFF64 - } - (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => { - elf::R_390_GOTPC - } - (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => { - elf::R_390_GOTPCDBL - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Sbf => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 64) => elf::R_SBF_64_64, - (RelocationKind::Absolute, _, 32) => elf::R_SBF_64_32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Sharc => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 32) => { - elf::R_SHARC_ADDR32_V3 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_SHARC_ADDR_VAR_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeA, 24) => { - elf::R_SHARC_PCRLONG_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeA, 6) => { - elf::R_SHARC_PCRSHORT_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeB, 6) => { - elf::R_SHARC_PCRSHORT_V3 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { - elf::R_SHARC_ADDR_VAR16_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 16) => { - elf::R_SHARC_DATA16_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 16) => { - elf::R_SHARC_DATA16_VISA_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 24) => { - elf::R_SHARC_ADDR24_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 6) => { - elf::R_SHARC_DATA6_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 6) => { - elf::R_SHARC_DATA6_VISA_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 7) => { - elf::R_SHARC_DATA7_VISA_V3 - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) { - // TODO: use R_SPARC_32/R_SPARC_64 if aligned. - (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32, - (RelocationKind::Absolute, _, 64) => elf::R_SPARC_UA64, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Xtensa => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_XTENSA_32, - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_XTENSA_32_PCREL - } - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - _ => { - if let RelocationKind::Elf(x) = reloc.kind { - x - } else { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - } - }; - let r_sym = symbol_offsets[reloc.symbol.0].index.0; - writer.write_relocation( - is_rela, - &Rel { - r_offset: reloc.offset, - r_sym, - r_type, - r_addend: reloc.addend, - }, - ); - } - } - } - - writer.write_shstrtab(); - - // Write section headers. - writer.write_null_section_header(); - - let symtab_index = writer.symtab_index(); - for (comdat, comdat_offset) in self.comdats.iter().zip(comdat_offsets.iter()) { - writer.write_comdat_section_header( - comdat_offset.str_id, - symtab_index, - symbol_offsets[comdat.symbol.0].index, - comdat_offset.offset, - comdat.sections.len(), - ); - } - for (index, section) in self.sections.iter().enumerate() { - let sh_type = match section.kind { - SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS, - SectionKind::Note => elf::SHT_NOTE, - SectionKind::Elf(sh_type) => sh_type, - _ => elf::SHT_PROGBITS, - }; - let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags { - sh_flags - } else { - match section.kind { - SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR, - SectionKind::Data | SectionKind::ReadOnlyDataWithRel => { - elf::SHF_ALLOC | elf::SHF_WRITE - } - SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, - SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE, - SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, - SectionKind::ReadOnlyData => elf::SHF_ALLOC, - SectionKind::ReadOnlyString => { - elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE - } - SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE, - SectionKind::Other - | SectionKind::Debug - | SectionKind::Metadata - | SectionKind::Linker - | SectionKind::Note - | SectionKind::Elf(_) => 0, - SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => { - return Err(Error(format!( - "unimplemented section `{}` kind {:?}", - section.name().unwrap_or(""), - section.kind - ))); - } - } - .into() - }; - // TODO: not sure if this is correct, maybe user should determine this - let sh_entsize = match section.kind { - SectionKind::ReadOnlyString | SectionKind::OtherString => 1, - _ => 0, - }; - writer.write_section_header(&SectionHeader { - name: Some(section_offsets[index].str_id), - sh_type, - sh_flags, - sh_addr: 0, - sh_offset: section_offsets[index].offset as u64, - sh_size: section.size, - sh_link: 0, - sh_info: 0, - sh_addralign: section.align, - sh_entsize, - }); - - if !section.relocations.is_empty() { - writer.write_relocation_section_header( - section_offsets[index].reloc_str_id.unwrap(), - section_offsets[index].index, - symtab_index, - section_offsets[index].reloc_offset, - section.relocations.len(), - is_rela, - ); - } - } - - writer.write_symtab_section_header(symtab_num_local); - writer.write_symtab_shndx_section_header(); - writer.write_strtab_section_header(); - writer.write_shstrtab_section_header(); - - debug_assert_eq!(writer.reserved_len(), writer.len()); - - Ok(()) - } -} diff --git a/vendor/object/src/write/elf/writer.rs b/vendor/object/src/write/elf/writer.rs deleted file mode 100644 index 9750924..0000000 --- a/vendor/object/src/write/elf/writer.rs +++ /dev/null @@ -1,2143 +0,0 @@ -//! Helper for writing ELF files. -use alloc::string::String; -use alloc::vec::Vec; -use core::mem; - -use crate::elf; -use crate::endian::*; -use crate::pod; -use crate::write::string::{StringId, StringTable}; -use crate::write::util; -use crate::write::{Error, Result, WritableBuffer}; - -/// The index of an ELF section. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SectionIndex(pub u32); - -/// The index of an ELF symbol. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SymbolIndex(pub u32); - -/// A helper for writing ELF files. -/// -/// Writing uses a two phase approach. The first phase builds up all of the information -/// that may need to be known ahead of time: -/// - build string tables -/// - reserve section indices -/// - reserve symbol indices -/// - reserve file ranges for headers and sections -/// -/// Some of the information has ordering requirements. For example, strings must be added -/// to string tables before reserving the file range for the string table. Symbol indices -/// must be reserved after reserving the section indices they reference. There are debug -/// asserts to check some of these requirements. -/// -/// The second phase writes everything out in order. Thus the caller must ensure writing -/// is in the same order that file ranges were reserved. There are debug asserts to assist -/// with checking this. -#[allow(missing_debug_implementations)] -pub struct Writer<'a> { - endian: Endianness, - is_64: bool, - is_mips64el: bool, - elf_align: usize, - - buffer: &'a mut dyn WritableBuffer, - len: usize, - - segment_offset: usize, - segment_num: u32, - - section_offset: usize, - section_num: u32, - - shstrtab: StringTable<'a>, - shstrtab_str_id: Option, - shstrtab_index: SectionIndex, - shstrtab_offset: usize, - shstrtab_data: Vec, - - need_strtab: bool, - strtab: StringTable<'a>, - strtab_str_id: Option, - strtab_index: SectionIndex, - strtab_offset: usize, - strtab_data: Vec, - - symtab_str_id: Option, - symtab_index: SectionIndex, - symtab_offset: usize, - symtab_num: u32, - - need_symtab_shndx: bool, - symtab_shndx_str_id: Option, - symtab_shndx_offset: usize, - symtab_shndx_data: Vec, - - need_dynstr: bool, - dynstr: StringTable<'a>, - dynstr_str_id: Option, - dynstr_index: SectionIndex, - dynstr_offset: usize, - dynstr_data: Vec, - - dynsym_str_id: Option, - dynsym_index: SectionIndex, - dynsym_offset: usize, - dynsym_num: u32, - - dynamic_str_id: Option, - dynamic_offset: usize, - dynamic_num: usize, - - hash_str_id: Option, - hash_offset: usize, - hash_size: usize, - - gnu_hash_str_id: Option, - gnu_hash_offset: usize, - gnu_hash_size: usize, - - gnu_versym_str_id: Option, - gnu_versym_offset: usize, - - gnu_verdef_str_id: Option, - gnu_verdef_offset: usize, - gnu_verdef_size: usize, - gnu_verdef_count: u16, - gnu_verdef_remaining: u16, - gnu_verdaux_remaining: u16, - - gnu_verneed_str_id: Option, - gnu_verneed_offset: usize, - gnu_verneed_size: usize, - gnu_verneed_count: u16, - gnu_verneed_remaining: u16, - gnu_vernaux_remaining: u16, - - gnu_attributes_str_id: Option, - gnu_attributes_offset: usize, - gnu_attributes_size: usize, -} - -impl<'a> Writer<'a> { - /// Create a new `Writer` for the given endianness and ELF class. - pub fn new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self { - let elf_align = if is_64 { 8 } else { 4 }; - Writer { - endian, - is_64, - // Determined later. - is_mips64el: false, - elf_align, - - buffer, - len: 0, - - segment_offset: 0, - segment_num: 0, - - section_offset: 0, - section_num: 0, - - shstrtab: StringTable::default(), - shstrtab_str_id: None, - shstrtab_index: SectionIndex(0), - shstrtab_offset: 0, - shstrtab_data: Vec::new(), - - need_strtab: false, - strtab: StringTable::default(), - strtab_str_id: None, - strtab_index: SectionIndex(0), - strtab_offset: 0, - strtab_data: Vec::new(), - - symtab_str_id: None, - symtab_index: SectionIndex(0), - symtab_offset: 0, - symtab_num: 0, - - need_symtab_shndx: false, - symtab_shndx_str_id: None, - symtab_shndx_offset: 0, - symtab_shndx_data: Vec::new(), - - need_dynstr: false, - dynstr: StringTable::default(), - dynstr_str_id: None, - dynstr_index: SectionIndex(0), - dynstr_offset: 0, - dynstr_data: Vec::new(), - - dynsym_str_id: None, - dynsym_index: SectionIndex(0), - dynsym_offset: 0, - dynsym_num: 0, - - dynamic_str_id: None, - dynamic_offset: 0, - dynamic_num: 0, - - hash_str_id: None, - hash_offset: 0, - hash_size: 0, - - gnu_hash_str_id: None, - gnu_hash_offset: 0, - gnu_hash_size: 0, - - gnu_versym_str_id: None, - gnu_versym_offset: 0, - - gnu_verdef_str_id: None, - gnu_verdef_offset: 0, - gnu_verdef_size: 0, - gnu_verdef_count: 0, - gnu_verdef_remaining: 0, - gnu_verdaux_remaining: 0, - - gnu_verneed_str_id: None, - gnu_verneed_offset: 0, - gnu_verneed_size: 0, - gnu_verneed_count: 0, - gnu_verneed_remaining: 0, - gnu_vernaux_remaining: 0, - - gnu_attributes_str_id: None, - gnu_attributes_offset: 0, - gnu_attributes_size: 0, - } - } - - /// Return the current file length that has been reserved. - pub fn reserved_len(&self) -> usize { - self.len - } - - /// Return the current file length that has been written. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.buffer.len() - } - - /// Reserve a file range with the given size and starting alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve(&mut self, len: usize, align_start: usize) -> usize { - if align_start > 1 { - self.len = util::align(self.len, align_start); - } - let offset = self.len; - self.len += len; - offset - } - - /// Write alignment padding bytes. - pub fn write_align(&mut self, align_start: usize) { - if align_start > 1 { - util::write_align(self.buffer, align_start); - } - } - - /// Write data. - /// - /// This is typically used to write section data. - pub fn write(&mut self, data: &[u8]) { - self.buffer.write_bytes(data); - } - - /// Reserve the file range up to the given file offset. - pub fn reserve_until(&mut self, offset: usize) { - debug_assert!(self.len <= offset); - self.len = offset; - } - - /// Write padding up to the given file offset. - pub fn pad_until(&mut self, offset: usize) { - debug_assert!(self.buffer.len() <= offset); - self.buffer.resize(offset); - } - - fn file_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - - /// Reserve the range for the file header. - /// - /// This must be at the start of the file. - pub fn reserve_file_header(&mut self) { - debug_assert_eq!(self.len, 0); - self.reserve(self.file_header_size(), 1); - } - - /// Write the file header. - /// - /// This must be at the start of the file. - /// - /// Fields that can be derived from known information are automatically set by this function. - pub fn write_file_header(&mut self, header: &FileHeader) -> Result<()> { - debug_assert_eq!(self.buffer.len(), 0); - - self.is_mips64el = - self.is_64 && self.endian.is_little_endian() && header.e_machine == elf::EM_MIPS; - - // Start writing. - self.buffer - .reserve(self.len) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - // Write file header. - let e_ident = elf::Ident { - magic: elf::ELFMAG, - class: if self.is_64 { - elf::ELFCLASS64 - } else { - elf::ELFCLASS32 - }, - data: if self.endian.is_little_endian() { - elf::ELFDATA2LSB - } else { - elf::ELFDATA2MSB - }, - version: elf::EV_CURRENT, - os_abi: header.os_abi, - abi_version: header.abi_version, - padding: [0; 7], - }; - - let e_ehsize = self.file_header_size() as u16; - - let e_phoff = self.segment_offset as u64; - let e_phentsize = if self.segment_num == 0 { - 0 - } else { - self.program_header_size() as u16 - }; - // TODO: overflow - let e_phnum = self.segment_num as u16; - - let e_shoff = self.section_offset as u64; - let e_shentsize = if self.section_num == 0 { - 0 - } else { - self.section_header_size() as u16 - }; - let e_shnum = if self.section_num >= elf::SHN_LORESERVE.into() { - 0 - } else { - self.section_num as u16 - }; - let e_shstrndx = if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { - elf::SHN_XINDEX - } else { - self.shstrtab_index.0 as u16 - }; - - let endian = self.endian; - if self.is_64 { - let file = elf::FileHeader64 { - e_ident, - e_type: U16::new(endian, header.e_type), - e_machine: U16::new(endian, header.e_machine), - e_version: U32::new(endian, elf::EV_CURRENT.into()), - e_entry: U64::new(endian, header.e_entry), - e_phoff: U64::new(endian, e_phoff), - e_shoff: U64::new(endian, e_shoff), - e_flags: U32::new(endian, header.e_flags), - e_ehsize: U16::new(endian, e_ehsize), - e_phentsize: U16::new(endian, e_phentsize), - e_phnum: U16::new(endian, e_phnum), - e_shentsize: U16::new(endian, e_shentsize), - e_shnum: U16::new(endian, e_shnum), - e_shstrndx: U16::new(endian, e_shstrndx), - }; - self.buffer.write(&file) - } else { - let file = elf::FileHeader32 { - e_ident, - e_type: U16::new(endian, header.e_type), - e_machine: U16::new(endian, header.e_machine), - e_version: U32::new(endian, elf::EV_CURRENT.into()), - e_entry: U32::new(endian, header.e_entry as u32), - e_phoff: U32::new(endian, e_phoff as u32), - e_shoff: U32::new(endian, e_shoff as u32), - e_flags: U32::new(endian, header.e_flags), - e_ehsize: U16::new(endian, e_ehsize), - e_phentsize: U16::new(endian, e_phentsize), - e_phnum: U16::new(endian, e_phnum), - e_shentsize: U16::new(endian, e_shentsize), - e_shnum: U16::new(endian, e_shnum), - e_shstrndx: U16::new(endian, e_shstrndx), - }; - self.buffer.write(&file); - } - - Ok(()) - } - - fn program_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - - /// Reserve the range for the program headers. - pub fn reserve_program_headers(&mut self, num: u32) { - debug_assert_eq!(self.segment_offset, 0); - if num == 0 { - return; - } - self.segment_num = num; - self.segment_offset = - self.reserve(num as usize * self.program_header_size(), self.elf_align); - } - - /// Write alignment padding bytes prior to the program headers. - pub fn write_align_program_headers(&mut self) { - if self.segment_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.segment_offset, self.buffer.len()); - } - - /// Write a program header. - pub fn write_program_header(&mut self, header: &ProgramHeader) { - let endian = self.endian; - if self.is_64 { - let header = elf::ProgramHeader64 { - p_type: U32::new(endian, header.p_type), - p_flags: U32::new(endian, header.p_flags), - p_offset: U64::new(endian, header.p_offset), - p_vaddr: U64::new(endian, header.p_vaddr), - p_paddr: U64::new(endian, header.p_paddr), - p_filesz: U64::new(endian, header.p_filesz), - p_memsz: U64::new(endian, header.p_memsz), - p_align: U64::new(endian, header.p_align), - }; - self.buffer.write(&header); - } else { - let header = elf::ProgramHeader32 { - p_type: U32::new(endian, header.p_type), - p_offset: U32::new(endian, header.p_offset as u32), - p_vaddr: U32::new(endian, header.p_vaddr as u32), - p_paddr: U32::new(endian, header.p_paddr as u32), - p_filesz: U32::new(endian, header.p_filesz as u32), - p_memsz: U32::new(endian, header.p_memsz as u32), - p_flags: U32::new(endian, header.p_flags), - p_align: U32::new(endian, header.p_align as u32), - }; - self.buffer.write(&header); - } - } - - /// Reserve the section index for the null section header. - /// - /// The null section header is usually automatically reserved, - /// but this can be used to force an empty section table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_null_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.section_num, 0); - if self.section_num == 0 { - self.section_num = 1; - } - SectionIndex(0) - } - - /// Reserve a section table index. - /// - /// Automatically also reserves the null section header if required. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.section_offset, 0); - if self.section_num == 0 { - self.section_num = 1; - } - let index = self.section_num; - self.section_num += 1; - SectionIndex(index) - } - - fn section_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - - /// Reserve the range for the section headers. - /// - /// This function does nothing if no sections were reserved. - /// This must be called after [`Self::reserve_section_index`] - /// and other functions that reserve section indices. - pub fn reserve_section_headers(&mut self) { - debug_assert_eq!(self.section_offset, 0); - if self.section_num == 0 { - return; - } - self.section_offset = self.reserve( - self.section_num as usize * self.section_header_size(), - self.elf_align, - ); - } - - /// Write the null section header. - /// - /// This must be the first section header that is written. - /// This function does nothing if no sections were reserved. - pub fn write_null_section_header(&mut self) { - if self.section_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.section_offset, self.buffer.len()); - self.write_section_header(&SectionHeader { - name: None, - sh_type: 0, - sh_flags: 0, - sh_addr: 0, - sh_offset: 0, - sh_size: if self.section_num >= elf::SHN_LORESERVE.into() { - self.section_num.into() - } else { - 0 - }, - sh_link: if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { - self.shstrtab_index.0 - } else { - 0 - }, - // TODO: e_phnum overflow - sh_info: 0, - sh_addralign: 0, - sh_entsize: 0, - }); - } - - /// Write a section header. - pub fn write_section_header(&mut self, section: &SectionHeader) { - let sh_name = if let Some(name) = section.name { - self.shstrtab.get_offset(name) as u32 - } else { - 0 - }; - let endian = self.endian; - if self.is_64 { - let section = elf::SectionHeader64 { - sh_name: U32::new(endian, sh_name), - sh_type: U32::new(endian, section.sh_type), - sh_flags: U64::new(endian, section.sh_flags), - sh_addr: U64::new(endian, section.sh_addr), - sh_offset: U64::new(endian, section.sh_offset), - sh_size: U64::new(endian, section.sh_size), - sh_link: U32::new(endian, section.sh_link), - sh_info: U32::new(endian, section.sh_info), - sh_addralign: U64::new(endian, section.sh_addralign), - sh_entsize: U64::new(endian, section.sh_entsize), - }; - self.buffer.write(§ion); - } else { - let section = elf::SectionHeader32 { - sh_name: U32::new(endian, sh_name), - sh_type: U32::new(endian, section.sh_type), - sh_flags: U32::new(endian, section.sh_flags as u32), - sh_addr: U32::new(endian, section.sh_addr as u32), - sh_offset: U32::new(endian, section.sh_offset as u32), - sh_size: U32::new(endian, section.sh_size as u32), - sh_link: U32::new(endian, section.sh_link), - sh_info: U32::new(endian, section.sh_info), - sh_addralign: U32::new(endian, section.sh_addralign as u32), - sh_entsize: U32::new(endian, section.sh_entsize as u32), - }; - self.buffer.write(§ion); - } - } - - /// Add a section name to the section header string table. - /// - /// This will be stored in the `.shstrtab` section. - /// - /// This must be called before [`Self::reserve_shstrtab`]. - pub fn add_section_name(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.shstrtab_offset, 0); - self.shstrtab.add(name) - } - - /// Reserve the range for the section header string table. - /// - /// This range is used for a section named `.shstrtab`. - /// - /// This function does nothing if no sections were reserved. - /// This must be called after [`Self::add_section_name`]. - /// and other functions that reserve section names and indices. - pub fn reserve_shstrtab(&mut self) { - debug_assert_eq!(self.shstrtab_offset, 0); - if self.section_num == 0 { - return; - } - // Start with null section name. - self.shstrtab_data = vec![0]; - self.shstrtab.write(1, &mut self.shstrtab_data); - self.shstrtab_offset = self.reserve(self.shstrtab_data.len(), 1); - } - - /// Write the section header string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_shstrtab(&mut self) { - if self.shstrtab_offset == 0 { - return; - } - debug_assert_eq!(self.shstrtab_offset, self.buffer.len()); - self.buffer.write_bytes(&self.shstrtab_data); - } - - /// Reserve the section index for the section header string table. - /// - /// This must be called before [`Self::reserve_shstrtab`] - /// and [`Self::reserve_section_headers`]. - pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.shstrtab_index, SectionIndex(0)); - self.shstrtab_str_id = Some(self.add_section_name(&b".shstrtab"[..])); - self.shstrtab_index = self.reserve_section_index(); - self.shstrtab_index - } - - /// Write the section header for the section header string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_shstrtab_section_header(&mut self) { - if self.shstrtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.shstrtab_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.shstrtab_offset as u64, - sh_size: self.shstrtab_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Add a string to the string table. - /// - /// This will be stored in the `.strtab` section. - /// - /// This must be called before [`Self::reserve_strtab`]. - pub fn add_string(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.strtab_offset, 0); - self.need_strtab = true; - self.strtab.add(name) - } - - /// Return true if `.strtab` is needed. - pub fn strtab_needed(&self) -> bool { - self.need_strtab - } - - /// Reserve the range for the string table. - /// - /// This range is used for a section named `.strtab`. - /// - /// This function does nothing if no strings or symbols were defined. - /// This must be called after [`Self::add_string`]. - pub fn reserve_strtab(&mut self) { - debug_assert_eq!(self.strtab_offset, 0); - if !self.need_strtab { - return; - } - // Start with null string. - self.strtab_data = vec![0]; - self.strtab.write(1, &mut self.strtab_data); - self.strtab_offset = self.reserve(self.strtab_data.len(), 1); - } - - /// Write the string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_strtab(&mut self) { - if self.strtab_offset == 0 { - return; - } - debug_assert_eq!(self.strtab_offset, self.buffer.len()); - self.buffer.write_bytes(&self.strtab_data); - } - - /// Reserve the section index for the string table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_strtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.strtab_index, SectionIndex(0)); - self.strtab_str_id = Some(self.add_section_name(&b".strtab"[..])); - self.strtab_index = self.reserve_section_index(); - self.strtab_index - } - - /// Write the section header for the string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_strtab_section_header(&mut self) { - if self.strtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.strtab_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.strtab_offset as u64, - sh_size: self.strtab_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Reserve the null symbol table entry. - /// - /// This will be stored in the `.symtab` section. - /// - /// The null symbol table entry is usually automatically reserved, - /// but this can be used to force an empty symbol table. - /// - /// This must be called before [`Self::reserve_symtab`]. - pub fn reserve_null_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.symtab_offset, 0); - debug_assert_eq!(self.symtab_num, 0); - self.symtab_num = 1; - // The symtab must link to a strtab. - self.need_strtab = true; - SymbolIndex(0) - } - - /// Reserve a symbol table entry. - /// - /// This will be stored in the `.symtab` section. - /// - /// `section_index` is used to determine whether `.symtab_shndx` is required. - /// - /// Automatically also reserves the null symbol if required. - /// Callers may assume that the returned indices will be sequential - /// starting at 1. - /// - /// This must be called before [`Self::reserve_symtab`] and - /// [`Self::reserve_symtab_shndx`]. - pub fn reserve_symbol_index(&mut self, section_index: Option) -> SymbolIndex { - debug_assert_eq!(self.symtab_offset, 0); - debug_assert_eq!(self.symtab_shndx_offset, 0); - if self.symtab_num == 0 { - self.symtab_num = 1; - // The symtab must link to a strtab. - self.need_strtab = true; - } - let index = self.symtab_num; - self.symtab_num += 1; - if let Some(section_index) = section_index { - if section_index.0 >= elf::SHN_LORESERVE.into() { - self.need_symtab_shndx = true; - } - } - SymbolIndex(index) - } - - /// Return the number of reserved symbol table entries. - /// - /// Includes the null symbol. - pub fn symbol_count(&self) -> u32 { - self.symtab_num - } - - fn symbol_size(&self) -> usize { - if self.is_64 { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - - /// Reserve the range for the symbol table. - /// - /// This range is used for a section named `.symtab`. - /// This function does nothing if no symbols were reserved. - /// This must be called after [`Self::reserve_symbol_index`]. - pub fn reserve_symtab(&mut self) { - debug_assert_eq!(self.symtab_offset, 0); - if self.symtab_num == 0 { - return; - } - self.symtab_offset = self.reserve( - self.symtab_num as usize * self.symbol_size(), - self.elf_align, - ); - } - - /// Write the null symbol. - /// - /// This must be the first symbol that is written. - /// This function does nothing if no symbols were reserved. - pub fn write_null_symbol(&mut self) { - if self.symtab_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.symtab_offset, self.buffer.len()); - if self.is_64 { - self.buffer.write(&elf::Sym64::::default()); - } else { - self.buffer.write(&elf::Sym32::::default()); - } - - if self.need_symtab_shndx { - self.symtab_shndx_data.write_pod(&U32::new(self.endian, 0)); - } - } - - /// Write a symbol. - pub fn write_symbol(&mut self, sym: &Sym) { - let st_name = if let Some(name) = sym.name { - self.strtab.get_offset(name) as u32 - } else { - 0 - }; - let st_shndx = if let Some(section) = sym.section { - if section.0 >= elf::SHN_LORESERVE as u32 { - elf::SHN_XINDEX - } else { - section.0 as u16 - } - } else { - sym.st_shndx - }; - - let endian = self.endian; - if self.is_64 { - let sym = elf::Sym64 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U64::new(endian, sym.st_value), - st_size: U64::new(endian, sym.st_size), - }; - self.buffer.write(&sym); - } else { - let sym = elf::Sym32 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U32::new(endian, sym.st_value as u32), - st_size: U32::new(endian, sym.st_size as u32), - }; - self.buffer.write(&sym); - } - - if self.need_symtab_shndx { - let section_index = sym.section.unwrap_or(SectionIndex(0)); - self.symtab_shndx_data - .write_pod(&U32::new(self.endian, section_index.0)); - } - } - - /// Reserve the section index for the symbol table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_symtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.symtab_index, SectionIndex(0)); - self.symtab_str_id = Some(self.add_section_name(&b".symtab"[..])); - self.symtab_index = self.reserve_section_index(); - self.symtab_index - } - - /// Return the section index of the symbol table. - pub fn symtab_index(&mut self) -> SectionIndex { - self.symtab_index - } - - /// Write the section header for the symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_symtab_section_header(&mut self, num_local: u32) { - if self.symtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.symtab_str_id, - sh_type: elf::SHT_SYMTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.symtab_offset as u64, - sh_size: self.symtab_num as u64 * self.symbol_size() as u64, - sh_link: self.strtab_index.0, - sh_info: num_local, - sh_addralign: self.elf_align as u64, - sh_entsize: self.symbol_size() as u64, - }); - } - - /// Return true if `.symtab_shndx` is needed. - pub fn symtab_shndx_needed(&self) -> bool { - self.need_symtab_shndx - } - - /// Reserve the range for the extended section indices for the symbol table. - /// - /// This range is used for a section named `.symtab_shndx`. - /// This also reserves a section index. - /// - /// This function does nothing if extended section indices are not needed. - /// This must be called after [`Self::reserve_symbol_index`]. - pub fn reserve_symtab_shndx(&mut self) { - debug_assert_eq!(self.symtab_shndx_offset, 0); - if !self.need_symtab_shndx { - return; - } - self.symtab_shndx_offset = self.reserve(self.symtab_num as usize * 4, 4); - self.symtab_shndx_data.reserve(self.symtab_num as usize * 4); - } - - /// Write the extended section indices for the symbol table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_symtab_shndx(&mut self) { - if self.symtab_shndx_offset == 0 { - return; - } - debug_assert_eq!(self.symtab_shndx_offset, self.buffer.len()); - debug_assert_eq!(self.symtab_num as usize * 4, self.symtab_shndx_data.len()); - self.buffer.write_bytes(&self.symtab_shndx_data); - } - - /// Reserve the section index for the extended section indices symbol table. - /// - /// You should check [`Self::symtab_shndx_needed`] before calling this - /// unless you have other means of knowing if this section is needed. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex { - debug_assert!(self.symtab_shndx_str_id.is_none()); - self.symtab_shndx_str_id = Some(self.add_section_name(&b".symtab_shndx"[..])); - self.reserve_section_index() - } - - /// Write the section header for the extended section indices for the symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_symtab_shndx_section_header(&mut self) { - if self.symtab_shndx_str_id.is_none() { - return; - } - let sh_size = if self.symtab_shndx_offset == 0 { - 0 - } else { - (self.symtab_num * 4) as u64 - }; - self.write_section_header(&SectionHeader { - name: self.symtab_shndx_str_id, - sh_type: elf::SHT_SYMTAB_SHNDX, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.symtab_shndx_offset as u64, - sh_size, - sh_link: self.symtab_index.0, - sh_info: 0, - sh_addralign: 4, - sh_entsize: 4, - }); - } - - /// Add a string to the dynamic string table. - /// - /// This will be stored in the `.dynstr` section. - /// - /// This must be called before [`Self::reserve_dynstr`]. - pub fn add_dynamic_string(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.dynstr_offset, 0); - self.need_dynstr = true; - self.dynstr.add(name) - } - - /// Get a string that was previously added to the dynamic string table. - /// - /// Panics if the string was not added. - pub fn get_dynamic_string(&self, name: &'a [u8]) -> StringId { - self.dynstr.get_id(name) - } - - /// Return true if `.dynstr` is needed. - pub fn dynstr_needed(&self) -> bool { - self.need_dynstr - } - - /// Reserve the range for the dynamic string table. - /// - /// This range is used for a section named `.dynstr`. - /// - /// This function does nothing if no dynamic strings or symbols were defined. - /// This must be called after [`Self::add_dynamic_string`]. - pub fn reserve_dynstr(&mut self) { - debug_assert_eq!(self.dynstr_offset, 0); - if !self.need_dynstr { - return; - } - // Start with null string. - self.dynstr_data = vec![0]; - self.dynstr.write(1, &mut self.dynstr_data); - self.dynstr_offset = self.reserve(self.dynstr_data.len(), 1); - } - - /// Write the dynamic string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_dynstr(&mut self) { - if self.dynstr_offset == 0 { - return; - } - debug_assert_eq!(self.dynstr_offset, self.buffer.len()); - self.buffer.write_bytes(&self.dynstr_data); - } - - /// Reserve the section index for the dynamic string table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.dynstr_index, SectionIndex(0)); - self.dynstr_str_id = Some(self.add_section_name(&b".dynstr"[..])); - self.dynstr_index = self.reserve_section_index(); - self.dynstr_index - } - - /// Return the section index of the dynamic string table. - pub fn dynstr_index(&mut self) -> SectionIndex { - self.dynstr_index - } - - /// Write the section header for the dynamic string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynstr_section_header(&mut self, sh_addr: u64) { - if self.dynstr_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynstr_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.dynstr_offset as u64, - sh_size: self.dynstr_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Reserve the null dynamic symbol table entry. - /// - /// This will be stored in the `.dynsym` section. - /// - /// The null dynamic symbol table entry is usually automatically reserved, - /// but this can be used to force an empty dynamic symbol table. - /// - /// This must be called before [`Self::reserve_dynsym`]. - pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.dynsym_offset, 0); - debug_assert_eq!(self.dynsym_num, 0); - self.dynsym_num = 1; - // The symtab must link to a strtab. - self.need_dynstr = true; - SymbolIndex(0) - } - - /// Reserve a dynamic symbol table entry. - /// - /// This will be stored in the `.dynsym` section. - /// - /// Automatically also reserves the null symbol if required. - /// Callers may assume that the returned indices will be sequential - /// starting at 1. - /// - /// This must be called before [`Self::reserve_dynsym`]. - pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.dynsym_offset, 0); - if self.dynsym_num == 0 { - self.dynsym_num = 1; - // The symtab must link to a strtab. - self.need_dynstr = true; - } - let index = self.dynsym_num; - self.dynsym_num += 1; - SymbolIndex(index) - } - - /// Return the number of reserved dynamic symbols. - /// - /// Includes the null symbol. - pub fn dynamic_symbol_count(&mut self) -> u32 { - self.dynsym_num - } - - /// Reserve the range for the dynamic symbol table. - /// - /// This range is used for a section named `.dynsym`. - /// - /// This function does nothing if no dynamic symbols were reserved. - /// This must be called after [`Self::reserve_dynamic_symbol_index`]. - pub fn reserve_dynsym(&mut self) { - debug_assert_eq!(self.dynsym_offset, 0); - if self.dynsym_num == 0 { - return; - } - self.dynsym_offset = self.reserve( - self.dynsym_num as usize * self.symbol_size(), - self.elf_align, - ); - } - - /// Write the null dynamic symbol. - /// - /// This must be the first dynamic symbol that is written. - /// This function does nothing if no dynamic symbols were reserved. - pub fn write_null_dynamic_symbol(&mut self) { - if self.dynsym_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.dynsym_offset, self.buffer.len()); - if self.is_64 { - self.buffer.write(&elf::Sym64::::default()); - } else { - self.buffer.write(&elf::Sym32::::default()); - } - } - - /// Write a dynamic symbol. - pub fn write_dynamic_symbol(&mut self, sym: &Sym) { - let st_name = if let Some(name) = sym.name { - self.dynstr.get_offset(name) as u32 - } else { - 0 - }; - - let st_shndx = if let Some(section) = sym.section { - if section.0 >= elf::SHN_LORESERVE as u32 { - // TODO: we don't actually write out .dynsym_shndx yet. - // This is unlikely to be needed though. - elf::SHN_XINDEX - } else { - section.0 as u16 - } - } else { - sym.st_shndx - }; - - let endian = self.endian; - if self.is_64 { - let sym = elf::Sym64 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U64::new(endian, sym.st_value), - st_size: U64::new(endian, sym.st_size), - }; - self.buffer.write(&sym); - } else { - let sym = elf::Sym32 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U32::new(endian, sym.st_value as u32), - st_size: U32::new(endian, sym.st_size as u32), - }; - self.buffer.write(&sym); - } - } - - /// Reserve the section index for the dynamic symbol table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.dynsym_index, SectionIndex(0)); - self.dynsym_str_id = Some(self.add_section_name(&b".dynsym"[..])); - self.dynsym_index = self.reserve_section_index(); - self.dynsym_index - } - - /// Return the section index of the dynamic symbol table. - pub fn dynsym_index(&mut self) -> SectionIndex { - self.dynsym_index - } - - /// Write the section header for the dynamic symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32) { - if self.dynsym_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynsym_str_id, - sh_type: elf::SHT_DYNSYM, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.dynsym_offset as u64, - sh_size: self.dynsym_num as u64 * self.symbol_size() as u64, - sh_link: self.dynstr_index.0, - sh_info: num_local, - sh_addralign: self.elf_align as u64, - sh_entsize: self.symbol_size() as u64, - }); - } - - fn dyn_size(&self) -> usize { - if self.is_64 { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - - /// Reserve the range for the `.dynamic` section. - /// - /// This function does nothing if `dynamic_num` is zero. - pub fn reserve_dynamic(&mut self, dynamic_num: usize) { - debug_assert_eq!(self.dynamic_offset, 0); - if dynamic_num == 0 { - return; - } - self.dynamic_num = dynamic_num; - self.dynamic_offset = self.reserve(dynamic_num * self.dyn_size(), self.elf_align); - } - - /// Write alignment padding bytes prior to the `.dynamic` section. - /// - /// This function does nothing if the section was not reserved. - pub fn write_align_dynamic(&mut self) { - if self.dynamic_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.dynamic_offset, self.buffer.len()); - } - - /// Write a dynamic string entry. - pub fn write_dynamic_string(&mut self, tag: u32, id: StringId) { - self.write_dynamic(tag, self.dynstr.get_offset(id) as u64); - } - - /// Write a dynamic value entry. - pub fn write_dynamic(&mut self, d_tag: u32, d_val: u64) { - debug_assert!(self.dynamic_offset <= self.buffer.len()); - let endian = self.endian; - if self.is_64 { - let d = elf::Dyn64 { - d_tag: U64::new(endian, d_tag.into()), - d_val: U64::new(endian, d_val), - }; - self.buffer.write(&d); - } else { - let d = elf::Dyn32 { - d_tag: U32::new(endian, d_tag), - d_val: U32::new(endian, d_val as u32), - }; - self.buffer.write(&d); - } - debug_assert!( - self.dynamic_offset + self.dynamic_num * self.dyn_size() >= self.buffer.len() - ); - } - - /// Reserve the section index for the dynamic table. - pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex { - debug_assert!(self.dynamic_str_id.is_none()); - self.dynamic_str_id = Some(self.add_section_name(&b".dynamic"[..])); - self.reserve_section_index() - } - - /// Write the section header for the dynamic table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynamic_section_header(&mut self, sh_addr: u64) { - if self.dynamic_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynamic_str_id, - sh_type: elf::SHT_DYNAMIC, - sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC).into(), - sh_addr, - sh_offset: self.dynamic_offset as u64, - sh_size: (self.dynamic_num * self.dyn_size()) as u64, - sh_link: self.dynstr_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: self.dyn_size() as u64, - }); - } - - fn rel_size(&self, is_rela: bool) -> usize { - if self.is_64 { - if is_rela { - mem::size_of::>() - } else { - mem::size_of::>() - } - } else { - if is_rela { - mem::size_of::>() - } else { - mem::size_of::>() - } - } - } - - /// Reserve a file range for a SysV hash section. - /// - /// `symbol_count` is the number of symbols in the hash, - /// not the total number of symbols. - pub fn reserve_hash(&mut self, bucket_count: u32, chain_count: u32) { - self.hash_size = mem::size_of::>() - + bucket_count as usize * 4 - + chain_count as usize * 4; - self.hash_offset = self.reserve(self.hash_size, self.elf_align); - } - - /// Write a SysV hash section. - /// - /// `chain_count` is the number of symbols in the hash. - /// The argument to `hash` will be in the range `0..chain_count`. - pub fn write_hash(&mut self, bucket_count: u32, chain_count: u32, hash: F) - where - F: Fn(u32) -> Option, - { - let mut buckets = vec![U32::new(self.endian, 0); bucket_count as usize]; - let mut chains = vec![U32::new(self.endian, 0); chain_count as usize]; - for i in 0..chain_count { - if let Some(hash) = hash(i) { - let bucket = hash % bucket_count; - chains[i as usize] = buckets[bucket as usize]; - buckets[bucket as usize] = U32::new(self.endian, i); - } - } - - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.hash_offset, self.buffer.len()); - self.buffer.write(&elf::HashHeader { - bucket_count: U32::new(self.endian, bucket_count), - chain_count: U32::new(self.endian, chain_count), - }); - self.buffer.write_slice(&buckets); - self.buffer.write_slice(&chains); - } - - /// Reserve the section index for the SysV hash table. - pub fn reserve_hash_section_index(&mut self) -> SectionIndex { - debug_assert!(self.hash_str_id.is_none()); - self.hash_str_id = Some(self.add_section_name(&b".hash"[..])); - self.reserve_section_index() - } - - /// Write the section header for the SysV hash table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_hash_section_header(&mut self, sh_addr: u64) { - if self.hash_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.hash_str_id, - sh_type: elf::SHT_HASH, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.hash_offset as u64, - sh_size: self.hash_size as u64, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: 4, - }); - } - - /// Reserve a file range for a GNU hash section. - /// - /// `symbol_count` is the number of symbols in the hash, - /// not the total number of symbols. - pub fn reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32) { - self.gnu_hash_size = mem::size_of::>() - + bloom_count as usize * self.elf_align - + bucket_count as usize * 4 - + symbol_count as usize * 4; - self.gnu_hash_offset = self.reserve(self.gnu_hash_size, self.elf_align); - } - - /// Write a GNU hash section. - /// - /// `symbol_count` is the number of symbols in the hash. - /// The argument to `hash` will be in the range `0..symbol_count`. - /// - /// This requires that symbols are already sorted by bucket. - pub fn write_gnu_hash( - &mut self, - symbol_base: u32, - bloom_shift: u32, - bloom_count: u32, - bucket_count: u32, - symbol_count: u32, - hash: F, - ) where - F: Fn(u32) -> u32, - { - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_hash_offset, self.buffer.len()); - self.buffer.write(&elf::GnuHashHeader { - bucket_count: U32::new(self.endian, bucket_count), - symbol_base: U32::new(self.endian, symbol_base), - bloom_count: U32::new(self.endian, bloom_count), - bloom_shift: U32::new(self.endian, bloom_shift), - }); - - // Calculate and write bloom filter. - if self.is_64 { - let mut bloom_filters = vec![0; bloom_count as usize]; - for i in 0..symbol_count { - let h = hash(i); - bloom_filters[((h / 64) & (bloom_count - 1)) as usize] |= - 1 << (h % 64) | 1 << ((h >> bloom_shift) % 64); - } - for bloom_filter in bloom_filters { - self.buffer.write(&U64::new(self.endian, bloom_filter)); - } - } else { - let mut bloom_filters = vec![0; bloom_count as usize]; - for i in 0..symbol_count { - let h = hash(i); - bloom_filters[((h / 32) & (bloom_count - 1)) as usize] |= - 1 << (h % 32) | 1 << ((h >> bloom_shift) % 32); - } - for bloom_filter in bloom_filters { - self.buffer.write(&U32::new(self.endian, bloom_filter)); - } - } - - // Write buckets. - // - // This requires that symbols are already sorted by bucket. - let mut bucket = 0; - for i in 0..symbol_count { - let symbol_bucket = hash(i) % bucket_count; - while bucket < symbol_bucket { - self.buffer.write(&U32::new(self.endian, 0)); - bucket += 1; - } - if bucket == symbol_bucket { - self.buffer.write(&U32::new(self.endian, symbol_base + i)); - bucket += 1; - } - } - while bucket < bucket_count { - self.buffer.write(&U32::new(self.endian, 0)); - bucket += 1; - } - - // Write hash values. - for i in 0..symbol_count { - let mut h = hash(i); - if i == symbol_count - 1 || h % bucket_count != hash(i + 1) % bucket_count { - h |= 1; - } else { - h &= !1; - } - self.buffer.write(&U32::new(self.endian, h)); - } - } - - /// Reserve the section index for the GNU hash table. - pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_hash_str_id.is_none()); - self.gnu_hash_str_id = Some(self.add_section_name(&b".gnu.hash"[..])); - self.reserve_section_index() - } - - /// Write the section header for the GNU hash table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_hash_section_header(&mut self, sh_addr: u64) { - if self.gnu_hash_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_hash_str_id, - sh_type: elf::SHT_GNU_HASH, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_hash_offset as u64, - sh_size: self.gnu_hash_size as u64, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the range for the `.gnu.version` section. - /// - /// This function does nothing if no dynamic symbols were reserved. - pub fn reserve_gnu_versym(&mut self) { - debug_assert_eq!(self.gnu_versym_offset, 0); - if self.dynsym_num == 0 { - return; - } - self.gnu_versym_offset = self.reserve(self.dynsym_num as usize * 2, 2); - } - - /// Write the null symbol version entry. - /// - /// This must be the first symbol version that is written. - /// This function does nothing if no dynamic symbols were reserved. - pub fn write_null_gnu_versym(&mut self) { - if self.dynsym_num == 0 { - return; - } - util::write_align(self.buffer, 2); - debug_assert_eq!(self.gnu_versym_offset, self.buffer.len()); - self.write_gnu_versym(0); - } - - /// Write a symbol version entry. - pub fn write_gnu_versym(&mut self, versym: u16) { - self.buffer.write(&U16::new(self.endian, versym)); - } - - /// Reserve the section index for the `.gnu.version` section. - pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_versym_str_id.is_none()); - self.gnu_versym_str_id = Some(self.add_section_name(&b".gnu.version"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_versym_section_header(&mut self, sh_addr: u64) { - if self.gnu_versym_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_versym_str_id, - sh_type: elf::SHT_GNU_VERSYM, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_versym_offset as u64, - sh_size: self.dynsym_num as u64 * 2, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: 2, - sh_entsize: 2, - }); - } - - /// Reserve the range for the `.gnu.version_d` section. - pub fn reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize) { - debug_assert_eq!(self.gnu_verdef_offset, 0); - if verdef_count == 0 { - return; - } - self.gnu_verdef_size = verdef_count * mem::size_of::>() - + verdaux_count * mem::size_of::>(); - self.gnu_verdef_offset = self.reserve(self.gnu_verdef_size, self.elf_align); - self.gnu_verdef_count = verdef_count as u16; - self.gnu_verdef_remaining = self.gnu_verdef_count; - } - - /// Write alignment padding bytes prior to a `.gnu.version_d` section. - pub fn write_align_gnu_verdef(&mut self) { - if self.gnu_verdef_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_verdef_offset, self.buffer.len()); - } - - /// Write a version definition entry. - pub fn write_gnu_verdef(&mut self, verdef: &Verdef) { - debug_assert_ne!(self.gnu_verdef_remaining, 0); - self.gnu_verdef_remaining -= 1; - let vd_next = if self.gnu_verdef_remaining == 0 { - 0 - } else { - mem::size_of::>() as u32 - + verdef.aux_count as u32 * mem::size_of::>() as u32 - }; - - self.gnu_verdaux_remaining = verdef.aux_count; - let vd_aux = if verdef.aux_count == 0 { - 0 - } else { - mem::size_of::>() as u32 - }; - - self.buffer.write(&elf::Verdef { - vd_version: U16::new(self.endian, verdef.version), - vd_flags: U16::new(self.endian, verdef.flags), - vd_ndx: U16::new(self.endian, verdef.index), - vd_cnt: U16::new(self.endian, verdef.aux_count), - vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))), - vd_aux: U32::new(self.endian, vd_aux), - vd_next: U32::new(self.endian, vd_next), - }); - self.write_gnu_verdaux(verdef.name); - } - - /// Write a version definition auxiliary entry. - pub fn write_gnu_verdaux(&mut self, name: StringId) { - debug_assert_ne!(self.gnu_verdaux_remaining, 0); - self.gnu_verdaux_remaining -= 1; - let vda_next = if self.gnu_verdaux_remaining == 0 { - 0 - } else { - mem::size_of::>() as u32 - }; - self.buffer.write(&elf::Verdaux { - vda_name: U32::new(self.endian, self.dynstr.get_offset(name) as u32), - vda_next: U32::new(self.endian, vda_next), - }); - } - - /// Reserve the section index for the `.gnu.version_d` section. - pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_verdef_str_id.is_none()); - self.gnu_verdef_str_id = Some(self.add_section_name(&b".gnu.version_d"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version_d` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_verdef_section_header(&mut self, sh_addr: u64) { - if self.gnu_verdef_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_verdef_str_id, - sh_type: elf::SHT_GNU_VERDEF, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_verdef_offset as u64, - sh_size: self.gnu_verdef_size as u64, - sh_link: self.dynstr_index.0, - sh_info: self.gnu_verdef_count.into(), - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the range for the `.gnu.version_r` section. - pub fn reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize) { - debug_assert_eq!(self.gnu_verneed_offset, 0); - if verneed_count == 0 { - return; - } - self.gnu_verneed_size = verneed_count * mem::size_of::>() - + vernaux_count * mem::size_of::>(); - self.gnu_verneed_offset = self.reserve(self.gnu_verneed_size, self.elf_align); - self.gnu_verneed_count = verneed_count as u16; - self.gnu_verneed_remaining = self.gnu_verneed_count; - } - - /// Write alignment padding bytes prior to a `.gnu.version_r` section. - pub fn write_align_gnu_verneed(&mut self) { - if self.gnu_verneed_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_verneed_offset, self.buffer.len()); - } - - /// Write a version need entry. - pub fn write_gnu_verneed(&mut self, verneed: &Verneed) { - debug_assert_ne!(self.gnu_verneed_remaining, 0); - self.gnu_verneed_remaining -= 1; - let vn_next = if self.gnu_verneed_remaining == 0 { - 0 - } else { - mem::size_of::>() as u32 - + verneed.aux_count as u32 * mem::size_of::>() as u32 - }; - - self.gnu_vernaux_remaining = verneed.aux_count; - let vn_aux = if verneed.aux_count == 0 { - 0 - } else { - mem::size_of::>() as u32 - }; - - self.buffer.write(&elf::Verneed { - vn_version: U16::new(self.endian, verneed.version), - vn_cnt: U16::new(self.endian, verneed.aux_count), - vn_file: U32::new(self.endian, self.dynstr.get_offset(verneed.file) as u32), - vn_aux: U32::new(self.endian, vn_aux), - vn_next: U32::new(self.endian, vn_next), - }); - } - - /// Write a version need auxiliary entry. - pub fn write_gnu_vernaux(&mut self, vernaux: &Vernaux) { - debug_assert_ne!(self.gnu_vernaux_remaining, 0); - self.gnu_vernaux_remaining -= 1; - let vna_next = if self.gnu_vernaux_remaining == 0 { - 0 - } else { - mem::size_of::>() as u32 - }; - self.buffer.write(&elf::Vernaux { - vna_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(vernaux.name))), - vna_flags: U16::new(self.endian, vernaux.flags), - vna_other: U16::new(self.endian, vernaux.index), - vna_name: U32::new(self.endian, self.dynstr.get_offset(vernaux.name) as u32), - vna_next: U32::new(self.endian, vna_next), - }); - } - - /// Reserve the section index for the `.gnu.version_r` section. - pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_verneed_str_id.is_none()); - self.gnu_verneed_str_id = Some(self.add_section_name(&b".gnu.version_r"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version_r` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_verneed_section_header(&mut self, sh_addr: u64) { - if self.gnu_verneed_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_verneed_str_id, - sh_type: elf::SHT_GNU_VERNEED, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_verneed_offset as u64, - sh_size: self.gnu_verneed_size as u64, - sh_link: self.dynstr_index.0, - sh_info: self.gnu_verneed_count.into(), - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the section index for the `.gnu.attributes` section. - pub fn reserve_gnu_attributes_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_attributes_str_id.is_none()); - self.gnu_attributes_str_id = Some(self.add_section_name(&b".gnu.attributes"[..])); - self.reserve_section_index() - } - - /// Reserve the range for the `.gnu.attributes` section. - pub fn reserve_gnu_attributes(&mut self, gnu_attributes_size: usize) { - debug_assert_eq!(self.gnu_attributes_offset, 0); - if gnu_attributes_size == 0 { - return; - } - self.gnu_attributes_size = gnu_attributes_size; - self.gnu_attributes_offset = self.reserve(self.gnu_attributes_size, self.elf_align); - } - - /// Write the section header for the `.gnu.attributes` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_attributes_section_header(&mut self) { - if self.gnu_attributes_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_attributes_str_id, - sh_type: elf::SHT_GNU_ATTRIBUTES, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.gnu_attributes_offset as u64, - sh_size: self.gnu_attributes_size as u64, - sh_link: self.dynstr_index.0, - sh_info: 0, // TODO - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Write the data for the `.gnu.attributes` section. - pub fn write_gnu_attributes(&mut self, data: &[u8]) { - if self.gnu_attributes_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_attributes_offset, self.buffer.len()); - self.buffer.write_bytes(data); - } - - /// Reserve a file range for the given number of relocations. - /// - /// Returns the offset of the range. - pub fn reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize { - self.reserve(count * self.rel_size(is_rela), self.elf_align) - } - - /// Write alignment padding bytes prior to a relocation section. - pub fn write_align_relocation(&mut self) { - util::write_align(self.buffer, self.elf_align); - } - - /// Write a relocation. - pub fn write_relocation(&mut self, is_rela: bool, rel: &Rel) { - let endian = self.endian; - if self.is_64 { - if is_rela { - let rel = elf::Rela64 { - r_offset: U64::new(endian, rel.r_offset), - r_info: elf::Rela64::r_info(endian, self.is_mips64el, rel.r_sym, rel.r_type), - r_addend: I64::new(endian, rel.r_addend), - }; - self.buffer.write(&rel); - } else { - let rel = elf::Rel64 { - r_offset: U64::new(endian, rel.r_offset), - r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type), - }; - self.buffer.write(&rel); - } - } else { - if is_rela { - let rel = elf::Rela32 { - r_offset: U32::new(endian, rel.r_offset as u32), - r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), - r_addend: I32::new(endian, rel.r_addend as i32), - }; - self.buffer.write(&rel); - } else { - let rel = elf::Rel32 { - r_offset: U32::new(endian, rel.r_offset as u32), - r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), - }; - self.buffer.write(&rel); - } - } - } - - /// Write the section header for a relocation section. - /// - /// `section` is the index of the section the relocations apply to, - /// or 0 if none. - /// - /// `symtab` is the index of the symbol table the relocations refer to, - /// or 0 if none. - /// - /// `offset` is the file offset of the relocations. - pub fn write_relocation_section_header( - &mut self, - name: StringId, - section: SectionIndex, - symtab: SectionIndex, - offset: usize, - count: usize, - is_rela: bool, - ) { - self.write_section_header(&SectionHeader { - name: Some(name), - sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL }, - sh_flags: elf::SHF_INFO_LINK.into(), - sh_addr: 0, - sh_offset: offset as u64, - sh_size: (count * self.rel_size(is_rela)) as u64, - sh_link: symtab.0, - sh_info: section.0, - sh_addralign: self.elf_align as u64, - sh_entsize: self.rel_size(is_rela) as u64, - }); - } - - /// Reserve a file range for a COMDAT section. - /// - /// `count` is the number of sections in the COMDAT group. - /// - /// Returns the offset of the range. - pub fn reserve_comdat(&mut self, count: usize) -> usize { - self.reserve((count + 1) * 4, 4) - } - - /// Write `GRP_COMDAT` at the start of the COMDAT section. - pub fn write_comdat_header(&mut self) { - util::write_align(self.buffer, 4); - self.buffer.write(&U32::new(self.endian, elf::GRP_COMDAT)); - } - - /// Write an entry in a COMDAT section. - pub fn write_comdat_entry(&mut self, entry: SectionIndex) { - self.buffer.write(&U32::new(self.endian, entry.0)); - } - - /// Write the section header for a COMDAT section. - pub fn write_comdat_section_header( - &mut self, - name: StringId, - symtab: SectionIndex, - symbol: SymbolIndex, - offset: usize, - count: usize, - ) { - self.write_section_header(&SectionHeader { - name: Some(name), - sh_type: elf::SHT_GROUP, - sh_flags: 0, - sh_addr: 0, - sh_offset: offset as u64, - sh_size: ((count + 1) * 4) as u64, - sh_link: symtab.0, - sh_info: symbol.0, - sh_addralign: 4, - sh_entsize: 4, - }); - } - - /// Return a helper for writing an attributes section. - pub fn attributes_writer(&self) -> AttributesWriter { - AttributesWriter::new(self.endian) - } -} - -/// A helper for writing an attributes section. -/// -/// Attributes have a variable length encoding, so it is awkward to write them in a -/// single pass. Instead, we build the entire attributes section data in memory, using -/// placeholders for unknown lengths that are filled in later. -#[allow(missing_debug_implementations)] -pub struct AttributesWriter { - endian: Endianness, - data: Vec, - subsection_offset: usize, - subsubsection_offset: usize, -} - -impl AttributesWriter { - /// Create a new `AttributesWriter` for the given endianness. - pub fn new(endian: Endianness) -> Self { - AttributesWriter { - endian, - data: vec![0x41], - subsection_offset: 0, - subsubsection_offset: 0, - } - } - - /// Start a new subsection with the given vendor name. - pub fn start_subsection(&mut self, vendor: &[u8]) { - debug_assert_eq!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.subsection_offset = self.data.len(); - self.data.extend_from_slice(&[0; 4]); - self.data.extend_from_slice(vendor); - self.data.push(0); - } - - /// End the subsection. - /// - /// The subsection length is automatically calculated and written. - pub fn end_subsection(&mut self) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - let length = self.data.len() - self.subsection_offset; - self.data[self.subsection_offset..][..4] - .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32))); - self.subsection_offset = 0; - } - - /// Start a new sub-subsection with the given tag. - pub fn start_subsubsection(&mut self, tag: u8) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.subsubsection_offset = self.data.len(); - self.data.push(tag); - self.data.extend_from_slice(&[0; 4]); - } - - /// Write a section or symbol index to the sub-subsection. - /// - /// The user must also call this function to write the terminating 0 index. - pub fn write_subsubsection_index(&mut self, index: u32) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, u64::from(index)); - } - - /// Write raw index data to the sub-subsection. - /// - /// The terminating 0 index is automatically written. - pub fn write_subsubsection_indices(&mut self, indices: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(indices); - self.data.push(0); - } - - /// Write an attribute tag to the sub-subsection. - pub fn write_attribute_tag(&mut self, tag: u64) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, tag); - } - - /// Write an attribute integer value to the sub-subsection. - pub fn write_attribute_integer(&mut self, value: u64) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, value); - } - - /// Write an attribute string value to the sub-subsection. - /// - /// The value must not include the null terminator. - pub fn write_attribute_string(&mut self, value: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(value); - self.data.push(0); - } - - /// Write raw attribute data to the sub-subsection. - pub fn write_subsubsection_attributes(&mut self, attributes: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(attributes); - } - - /// End the sub-subsection. - /// - /// The sub-subsection length is automatically calculated and written. - pub fn end_subsubsection(&mut self) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - let length = self.data.len() - self.subsubsection_offset; - self.data[self.subsubsection_offset + 1..][..4] - .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32))); - self.subsubsection_offset = 0; - } - - /// Return the completed section data. - pub fn data(self) -> Vec { - debug_assert_eq!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.data - } -} - -/// Native endian version of [`elf::FileHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct FileHeader { - pub os_abi: u8, - pub abi_version: u8, - pub e_type: u16, - pub e_machine: u16, - pub e_entry: u64, - pub e_flags: u32, -} - -/// Native endian version of [`elf::ProgramHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct ProgramHeader { - pub p_type: u32, - pub p_flags: u32, - pub p_offset: u64, - pub p_vaddr: u64, - pub p_paddr: u64, - pub p_filesz: u64, - pub p_memsz: u64, - pub p_align: u64, -} - -/// Native endian version of [`elf::SectionHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct SectionHeader { - pub name: Option, - pub sh_type: u32, - pub sh_flags: u64, - pub sh_addr: u64, - pub sh_offset: u64, - pub sh_size: u64, - pub sh_link: u32, - pub sh_info: u32, - pub sh_addralign: u64, - pub sh_entsize: u64, -} - -/// Native endian version of [`elf::Sym64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Sym { - pub name: Option, - pub section: Option, - pub st_info: u8, - pub st_other: u8, - pub st_shndx: u16, - pub st_value: u64, - pub st_size: u64, -} - -/// Unified native endian version of [`elf::Rel64`] and [`elf::Rela64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Rel { - pub r_offset: u64, - pub r_sym: u32, - pub r_type: u32, - pub r_addend: i64, -} - -/// Information required for writing [`elf::Verdef`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Verdef { - pub version: u16, - pub flags: u16, - pub index: u16, - pub aux_count: u16, - /// The name for the first [`elf::Verdaux`] entry. - pub name: StringId, -} - -/// Information required for writing [`elf::Verneed`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Verneed { - pub version: u16, - pub aux_count: u16, - pub file: StringId, -} - -/// Information required for writing [`elf::Vernaux`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Vernaux { - pub flags: u16, - pub index: u16, - pub name: StringId, -} diff --git a/vendor/object/src/write/macho.rs b/vendor/object/src/write/macho.rs deleted file mode 100644 index 1c61523..0000000 --- a/vendor/object/src/write/macho.rs +++ /dev/null @@ -1,1095 +0,0 @@ -use core::mem; - -use crate::endian::*; -use crate::macho; -use crate::write::string::*; -use crate::write::util::*; -use crate::write::*; -use crate::AddressSize; - -#[derive(Default, Clone, Copy)] -struct SectionOffsets { - index: usize, - offset: usize, - address: u64, - reloc_offset: usize, - reloc_count: usize, -} - -#[derive(Default, Clone, Copy)] -struct SymbolOffsets { - index: usize, - str_id: Option, -} - -/// The customizable portion of a [`macho::BuildVersionCommand`]. -#[derive(Debug, Default, Clone, Copy)] -#[non_exhaustive] // May want to add the tool list? -pub struct MachOBuildVersion { - /// One of the `PLATFORM_` constants (for example, - /// [`object::macho::PLATFORM_MACOS`](macho::PLATFORM_MACOS)). - pub platform: u32, - /// The minimum OS version, where `X.Y.Z` is encoded in nibbles as - /// `xxxx.yy.zz`. - pub minos: u32, - /// The SDK version as `X.Y.Z`, where `X.Y.Z` is encoded in nibbles as - /// `xxxx.yy.zz`. - pub sdk: u32, -} - -impl MachOBuildVersion { - fn cmdsize(&self) -> u32 { - // Same size for both endianness, and we don't have `ntools`. - let sz = mem::size_of::>(); - debug_assert!(sz <= u32::MAX as usize); - sz as u32 - } -} - -// Public methods. -impl<'a> Object<'a> { - /// Specify the Mach-O CPU subtype. - /// - /// Requires `feature = "macho"`. - #[inline] - pub fn set_macho_cpu_subtype(&mut self, cpu_subtype: u32) { - self.macho_cpu_subtype = Some(cpu_subtype); - } - - /// Specify information for a Mach-O `LC_BUILD_VERSION` command. - /// - /// Requires `feature = "macho"`. - #[inline] - pub fn set_macho_build_version(&mut self, info: MachOBuildVersion) { - self.macho_build_version = Some(info); - } -} - -// Private methods. -impl<'a> Object<'a> { - pub(crate) fn macho_set_subsections_via_symbols(&mut self) { - let flags = match self.flags { - FileFlags::MachO { flags } => flags, - _ => 0, - }; - self.flags = FileFlags::MachO { - flags: flags | macho::MH_SUBSECTIONS_VIA_SYMBOLS, - }; - } - - pub(crate) fn macho_segment_name(&self, segment: StandardSegment) -> &'static [u8] { - match segment { - StandardSegment::Text => &b"__TEXT"[..], - StandardSegment::Data => &b"__DATA"[..], - StandardSegment::Debug => &b"__DWARF"[..], - } - } - - pub(crate) fn macho_section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match section { - StandardSection::Text => ( - &b"__TEXT"[..], - &b"__text"[..], - SectionKind::Text, - SectionFlags::None, - ), - StandardSection::Data => ( - &b"__DATA"[..], - &b"__data"[..], - SectionKind::Data, - SectionFlags::None, - ), - StandardSection::ReadOnlyData => ( - &b"__TEXT"[..], - &b"__const"[..], - SectionKind::ReadOnlyData, - SectionFlags::None, - ), - StandardSection::ReadOnlyDataWithRel => ( - &b"__DATA"[..], - &b"__const"[..], - SectionKind::ReadOnlyDataWithRel, - SectionFlags::None, - ), - StandardSection::ReadOnlyString => ( - &b"__TEXT"[..], - &b"__cstring"[..], - SectionKind::ReadOnlyString, - SectionFlags::None, - ), - StandardSection::UninitializedData => ( - &b"__DATA"[..], - &b"__bss"[..], - SectionKind::UninitializedData, - SectionFlags::None, - ), - StandardSection::Tls => ( - &b"__DATA"[..], - &b"__thread_data"[..], - SectionKind::Tls, - SectionFlags::None, - ), - StandardSection::UninitializedTls => ( - &b"__DATA"[..], - &b"__thread_bss"[..], - SectionKind::UninitializedTls, - SectionFlags::None, - ), - StandardSection::TlsVariables => ( - &b"__DATA"[..], - &b"__thread_vars"[..], - SectionKind::TlsVariables, - SectionFlags::None, - ), - StandardSection::Common => ( - &b"__DATA"[..], - &b"__common"[..], - SectionKind::Common, - SectionFlags::None, - ), - StandardSection::GnuProperty => { - // Unsupported section. - (&[], &[], SectionKind::Note, SectionFlags::None) - } - } - } - - fn macho_tlv_bootstrap(&mut self) -> SymbolId { - match self.tlv_bootstrap { - Some(id) => id, - None => { - let id = self.add_symbol(Symbol { - name: b"_tlv_bootstrap".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Text, - scope: SymbolScope::Dynamic, - weak: false, - section: SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - self.tlv_bootstrap = Some(id); - id - } - } - } - - /// Create the `__thread_vars` entry for a TLS variable. - /// - /// The symbol given by `symbol_id` will be updated to point to this entry. - /// - /// A new `SymbolId` will be returned. The caller must update this symbol - /// to point to the initializer. - /// - /// If `symbol_id` is not for a TLS variable, then it is returned unchanged. - pub(crate) fn macho_add_thread_var(&mut self, symbol_id: SymbolId) -> SymbolId { - let symbol = self.symbol_mut(symbol_id); - if symbol.kind != SymbolKind::Tls { - return symbol_id; - } - - // Create the initializer symbol. - let mut name = symbol.name.clone(); - name.extend_from_slice(b"$tlv$init"); - let init_symbol_id = self.add_raw_symbol(Symbol { - name, - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Compilation, - weak: false, - section: SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - - // Add the tlv entry. - // Three pointers in size: - // - __tlv_bootstrap - used to make sure support exists - // - spare pointer - used when mapped by the runtime - // - pointer to symbol initializer - let section = self.section_id(StandardSection::TlsVariables); - let address_size = self.architecture.address_size().unwrap().bytes(); - let size = u64::from(address_size) * 3; - let data = vec![0; size as usize]; - let offset = self.append_section_data(section, &data, u64::from(address_size)); - - let tlv_bootstrap = self.macho_tlv_bootstrap(); - self.add_relocation( - section, - Relocation { - offset, - size: address_size * 8, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: tlv_bootstrap, - addend: 0, - }, - ) - .unwrap(); - self.add_relocation( - section, - Relocation { - offset: offset + u64::from(address_size) * 2, - size: address_size * 8, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: init_symbol_id, - addend: 0, - }, - ) - .unwrap(); - - // Update the symbol to point to the tlv. - let symbol = self.symbol_mut(symbol_id); - symbol.value = offset; - symbol.size = size; - symbol.section = SymbolSection::Section(section); - - init_symbol_id - } - - pub(crate) fn macho_fixup_relocation(&mut self, relocation: &mut Relocation) -> i64 { - let relative = match relocation.kind { - RelocationKind::Relative - | RelocationKind::GotRelative - | RelocationKind::PltRelative - | RelocationKind::MachO { relative: true, .. } => true, - _ => false, - }; - if relative { - // For PC relative relocations on some architectures, the - // addend does not include the offset required due to the - // PC being different from the place of the relocation. - // This differs from other file formats, so adjust the - // addend here to account for this. - let pcrel_offset = match self.architecture { - Architecture::I386 => 4, - Architecture::X86_64 => match relocation.kind { - RelocationKind::MachO { - value: macho::X86_64_RELOC_SIGNED_1, - .. - } => 5, - RelocationKind::MachO { - value: macho::X86_64_RELOC_SIGNED_2, - .. - } => 6, - RelocationKind::MachO { - value: macho::X86_64_RELOC_SIGNED_4, - .. - } => 8, - _ => 4, - }, - // TODO: maybe missing support for some architectures and relocations - _ => 0, - }; - relocation.addend += pcrel_offset; - } - // Aarch64 relocs of these sizes act as if they are double-word length - if self.architecture == Architecture::Aarch64 && matches!(relocation.size, 12 | 21 | 26) { - relocation.size = 32; - } - // Check for relocations that use an explicit addend. - if self.architecture == Architecture::Aarch64 { - if relocation.encoding == RelocationEncoding::AArch64Call { - return 0; - } - if let RelocationKind::MachO { value, .. } = relocation.kind { - match value { - macho::ARM64_RELOC_BRANCH26 - | macho::ARM64_RELOC_PAGE21 - | macho::ARM64_RELOC_PAGEOFF12 => return 0, - _ => {} - } - } - } - // Signify implicit addend. - let constant = relocation.addend; - relocation.addend = 0; - constant - } - - pub(crate) fn macho_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - let address_size = self.architecture.address_size().unwrap(); - let endian = self.endian; - let macho32 = MachO32 { endian }; - let macho64 = MachO64 { endian }; - let macho: &dyn MachO = match address_size { - AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => &macho32, - AddressSize::U64 => &macho64, - }; - let pointer_align = address_size.bytes() as usize; - - // Calculate offsets of everything, and build strtab. - let mut offset = 0; - - // Calculate size of Mach-O header. - offset += macho.mach_header_size(); - - // Calculate size of commands. - let mut ncmds = 0; - let command_offset = offset; - - // Calculate size of segment command and section headers. - let segment_command_offset = offset; - let segment_command_len = - macho.segment_command_size() + self.sections.len() * macho.section_header_size(); - offset += segment_command_len; - ncmds += 1; - - // Calculate size of build version. - let build_version_offset = offset; - if let Some(version) = &self.macho_build_version { - offset += version.cmdsize() as usize; - ncmds += 1; - } - - // Calculate size of symtab command. - let symtab_command_offset = offset; - let symtab_command_len = mem::size_of::>(); - offset += symtab_command_len; - ncmds += 1; - - // Calculate size of dysymtab command. - let dysymtab_command_offset = offset; - let dysymtab_command_len = mem::size_of::>(); - offset += dysymtab_command_len; - ncmds += 1; - - let sizeofcmds = offset - command_offset; - - // Calculate size of section data. - // Section data can immediately follow the load commands without any alignment padding. - let segment_file_offset = offset; - let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; - let mut address = 0; - for (index, section) in self.sections.iter().enumerate() { - section_offsets[index].index = 1 + index; - if !section.is_bss() { - address = align_u64(address, section.align); - section_offsets[index].address = address; - section_offsets[index].offset = segment_file_offset + address as usize; - address += section.size; - } - } - let segment_file_size = address as usize; - offset += address as usize; - for (index, section) in self.sections.iter().enumerate() { - if section.is_bss() { - debug_assert!(section.data.is_empty()); - address = align_u64(address, section.align); - section_offsets[index].address = address; - address += section.size; - } - } - - // Partition symbols and add symbol strings to strtab. - let mut strtab = StringTable::default(); - let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; - let mut local_symbols = vec![]; - let mut external_symbols = vec![]; - let mut undefined_symbols = vec![]; - for (index, symbol) in self.symbols.iter().enumerate() { - // The unified API allows creating symbols that we don't emit, so filter - // them out here. - // - // Since we don't actually emit the symbol kind, we validate it here too. - match symbol.kind { - SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls | SymbolKind::Unknown => {} - SymbolKind::File | SymbolKind::Section => continue, - SymbolKind::Null | SymbolKind::Label => { - return Err(Error(format!( - "unimplemented symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - symbol.kind - ))); - } - } - if !symbol.name.is_empty() { - symbol_offsets[index].str_id = Some(strtab.add(&symbol.name)); - } - if symbol.is_undefined() { - undefined_symbols.push(index); - } else if symbol.is_local() { - local_symbols.push(index); - } else { - external_symbols.push(index); - } - } - - external_symbols.sort_by_key(|index| &*self.symbols[*index].name); - undefined_symbols.sort_by_key(|index| &*self.symbols[*index].name); - - // Count symbols. - let mut nsyms = 0; - for index in local_symbols - .iter() - .copied() - .chain(external_symbols.iter().copied()) - .chain(undefined_symbols.iter().copied()) - { - symbol_offsets[index].index = nsyms; - nsyms += 1; - } - - // Calculate size of relocations. - for (index, section) in self.sections.iter().enumerate() { - let count: usize = section - .relocations - .iter() - .map(|reloc| 1 + usize::from(reloc.addend != 0)) - .sum(); - if count != 0 { - offset = align(offset, pointer_align); - section_offsets[index].reloc_offset = offset; - section_offsets[index].reloc_count = count; - let len = count * mem::size_of::>(); - offset += len; - } - } - - // Calculate size of symtab. - offset = align(offset, pointer_align); - let symtab_offset = offset; - let symtab_len = nsyms * macho.nlist_size(); - offset += symtab_len; - - // Calculate size of strtab. - let strtab_offset = offset; - // Start with null name. - let mut strtab_data = vec![0]; - strtab.write(1, &mut strtab_data); - write_align(&mut strtab_data, pointer_align); - offset += strtab_data.len(); - - // Start writing. - buffer - .reserve(offset) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - // Write file header. - let (cputype, mut cpusubtype) = match (self.architecture, self.sub_architecture) { - (Architecture::Arm, None) => (macho::CPU_TYPE_ARM, macho::CPU_SUBTYPE_ARM_ALL), - (Architecture::Aarch64, None) => (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64_ALL), - (Architecture::Aarch64, Some(SubArchitecture::Arm64E)) => { - (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64E) - } - (Architecture::Aarch64_Ilp32, None) => { - (macho::CPU_TYPE_ARM64_32, macho::CPU_SUBTYPE_ARM64_32_V8) - } - (Architecture::I386, None) => (macho::CPU_TYPE_X86, macho::CPU_SUBTYPE_I386_ALL), - (Architecture::X86_64, None) => (macho::CPU_TYPE_X86_64, macho::CPU_SUBTYPE_X86_64_ALL), - (Architecture::PowerPc, None) => { - (macho::CPU_TYPE_POWERPC, macho::CPU_SUBTYPE_POWERPC_ALL) - } - (Architecture::PowerPc64, None) => { - (macho::CPU_TYPE_POWERPC64, macho::CPU_SUBTYPE_POWERPC_ALL) - } - _ => { - return Err(Error(format!( - "unimplemented architecture {:?} with sub-architecture {:?}", - self.architecture, self.sub_architecture - ))); - } - }; - - if let Some(cpu_subtype) = self.macho_cpu_subtype { - cpusubtype = cpu_subtype; - } - - let flags = match self.flags { - FileFlags::MachO { flags } => flags, - _ => 0, - }; - macho.write_mach_header( - buffer, - MachHeader { - cputype, - cpusubtype, - filetype: macho::MH_OBJECT, - ncmds, - sizeofcmds: sizeofcmds as u32, - flags, - }, - ); - - // Write segment command. - debug_assert_eq!(segment_command_offset, buffer.len()); - macho.write_segment_command( - buffer, - SegmentCommand { - cmdsize: segment_command_len as u32, - segname: [0; 16], - vmaddr: 0, - vmsize: address, - fileoff: segment_file_offset as u64, - filesize: segment_file_size as u64, - maxprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE, - initprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE, - nsects: self.sections.len() as u32, - flags: 0, - }, - ); - - // Write section headers. - for (index, section) in self.sections.iter().enumerate() { - let mut sectname = [0; 16]; - sectname - .get_mut(..section.name.len()) - .ok_or_else(|| { - Error(format!( - "section name `{}` is too long", - section.name().unwrap_or(""), - )) - })? - .copy_from_slice(§ion.name); - let mut segname = [0; 16]; - segname - .get_mut(..section.segment.len()) - .ok_or_else(|| { - Error(format!( - "segment name `{}` is too long", - section.segment().unwrap_or(""), - )) - })? - .copy_from_slice(§ion.segment); - let flags = if let SectionFlags::MachO { flags } = section.flags { - flags - } else { - match section.kind { - SectionKind::Text => { - macho::S_ATTR_PURE_INSTRUCTIONS | macho::S_ATTR_SOME_INSTRUCTIONS - } - SectionKind::Data => 0, - SectionKind::ReadOnlyData | SectionKind::ReadOnlyDataWithRel => 0, - SectionKind::ReadOnlyString => macho::S_CSTRING_LITERALS, - SectionKind::UninitializedData | SectionKind::Common => macho::S_ZEROFILL, - SectionKind::Tls => macho::S_THREAD_LOCAL_REGULAR, - SectionKind::UninitializedTls => macho::S_THREAD_LOCAL_ZEROFILL, - SectionKind::TlsVariables => macho::S_THREAD_LOCAL_VARIABLES, - SectionKind::Debug => macho::S_ATTR_DEBUG, - SectionKind::OtherString => macho::S_CSTRING_LITERALS, - SectionKind::Other | SectionKind::Linker | SectionKind::Metadata => 0, - SectionKind::Note | SectionKind::Unknown | SectionKind::Elf(_) => { - return Err(Error(format!( - "unimplemented section `{}` kind {:?}", - section.name().unwrap_or(""), - section.kind - ))); - } - } - }; - macho.write_section( - buffer, - SectionHeader { - sectname, - segname, - addr: section_offsets[index].address, - size: section.size, - offset: section_offsets[index].offset as u32, - align: section.align.trailing_zeros(), - reloff: section_offsets[index].reloc_offset as u32, - nreloc: section_offsets[index].reloc_count as u32, - flags, - }, - ); - } - - // Write build version. - if let Some(version) = &self.macho_build_version { - debug_assert_eq!(build_version_offset, buffer.len()); - buffer.write(&macho::BuildVersionCommand { - cmd: U32::new(endian, macho::LC_BUILD_VERSION), - cmdsize: U32::new(endian, version.cmdsize()), - platform: U32::new(endian, version.platform), - minos: U32::new(endian, version.minos), - sdk: U32::new(endian, version.sdk), - ntools: U32::new(endian, 0), - }); - } - - // Write symtab command. - debug_assert_eq!(symtab_command_offset, buffer.len()); - let symtab_command = macho::SymtabCommand { - cmd: U32::new(endian, macho::LC_SYMTAB), - cmdsize: U32::new(endian, symtab_command_len as u32), - symoff: U32::new(endian, symtab_offset as u32), - nsyms: U32::new(endian, nsyms as u32), - stroff: U32::new(endian, strtab_offset as u32), - strsize: U32::new(endian, strtab_data.len() as u32), - }; - buffer.write(&symtab_command); - - // Write dysymtab command. - debug_assert_eq!(dysymtab_command_offset, buffer.len()); - let dysymtab_command = macho::DysymtabCommand { - cmd: U32::new(endian, macho::LC_DYSYMTAB), - cmdsize: U32::new(endian, dysymtab_command_len as u32), - ilocalsym: U32::new(endian, 0), - nlocalsym: U32::new(endian, local_symbols.len() as u32), - iextdefsym: U32::new(endian, local_symbols.len() as u32), - nextdefsym: U32::new(endian, external_symbols.len() as u32), - iundefsym: U32::new( - endian, - local_symbols.len() as u32 + external_symbols.len() as u32, - ), - nundefsym: U32::new(endian, undefined_symbols.len() as u32), - tocoff: U32::default(), - ntoc: U32::default(), - modtaboff: U32::default(), - nmodtab: U32::default(), - extrefsymoff: U32::default(), - nextrefsyms: U32::default(), - indirectsymoff: U32::default(), - nindirectsyms: U32::default(), - extreloff: U32::default(), - nextrel: U32::default(), - locreloff: U32::default(), - nlocrel: U32::default(), - }; - buffer.write(&dysymtab_command); - - // Write section data. - for (index, section) in self.sections.iter().enumerate() { - if !section.is_bss() { - buffer.resize(section_offsets[index].offset); - buffer.write_bytes(§ion.data); - } - } - debug_assert_eq!(segment_file_offset + segment_file_size, buffer.len()); - - // Write relocations. - for (index, section) in self.sections.iter().enumerate() { - if !section.relocations.is_empty() { - write_align(buffer, pointer_align); - debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); - for reloc in §ion.relocations { - let r_length = match reloc.size { - 8 => 0, - 16 => 1, - 32 => 2, - 64 => 3, - _ => return Err(Error(format!("unimplemented reloc size {:?}", reloc))), - }; - - // Write explicit addend. - if reloc.addend != 0 { - let r_type = match self.architecture { - Architecture::Aarch64 | Architecture::Aarch64_Ilp32 => { - macho::ARM64_RELOC_ADDEND - } - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))) - } - }; - - let reloc_info = macho::RelocationInfo { - r_address: reloc.offset as u32, - r_symbolnum: reloc.addend as u32, - r_pcrel: false, - r_length, - r_extern: false, - r_type, - }; - buffer.write(&reloc_info.relocation(endian)); - } - - let r_extern; - let r_symbolnum; - let symbol = &self.symbols[reloc.symbol.0]; - if symbol.kind == SymbolKind::Section { - r_symbolnum = section_offsets[symbol.section.id().unwrap().0].index as u32; - r_extern = false; - } else { - r_symbolnum = symbol_offsets[reloc.symbol.0].index as u32; - r_extern = true; - } - let (r_pcrel, r_type) = match self.architecture { - Architecture::I386 => match reloc.kind { - RelocationKind::Absolute => (false, macho::GENERIC_RELOC_VANILLA), - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::X86_64 => match (reloc.kind, reloc.encoding) { - (RelocationKind::Absolute, RelocationEncoding::Generic) => { - (false, macho::X86_64_RELOC_UNSIGNED) - } - (RelocationKind::Relative, RelocationEncoding::Generic) => { - (true, macho::X86_64_RELOC_SIGNED) - } - (RelocationKind::Relative, RelocationEncoding::X86RipRelative) => { - (true, macho::X86_64_RELOC_SIGNED) - } - (RelocationKind::Relative, RelocationEncoding::X86Branch) => { - (true, macho::X86_64_RELOC_BRANCH) - } - (RelocationKind::PltRelative, RelocationEncoding::X86Branch) => { - (true, macho::X86_64_RELOC_BRANCH) - } - (RelocationKind::GotRelative, RelocationEncoding::Generic) => { - (true, macho::X86_64_RELOC_GOT) - } - ( - RelocationKind::GotRelative, - RelocationEncoding::X86RipRelativeMovq, - ) => (true, macho::X86_64_RELOC_GOT_LOAD), - (RelocationKind::MachO { value, relative }, _) => (relative, value), - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Aarch64 | Architecture::Aarch64_Ilp32 => { - match (reloc.kind, reloc.encoding) { - (RelocationKind::Absolute, RelocationEncoding::Generic) => { - (false, macho::ARM64_RELOC_UNSIGNED) - } - (RelocationKind::Relative, RelocationEncoding::AArch64Call) => { - (true, macho::ARM64_RELOC_BRANCH26) - } - ( - RelocationKind::MachO { value, relative }, - RelocationEncoding::Generic, - ) => (relative, value), - _ => { - return Err(Error(format!( - "unimplemented relocation {:?}", - reloc - ))); - } - } - } - _ => { - if let RelocationKind::MachO { value, relative } = reloc.kind { - (relative, value) - } else { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - } - }; - let reloc_info = macho::RelocationInfo { - r_address: reloc.offset as u32, - r_symbolnum, - r_pcrel, - r_length, - r_extern, - r_type, - }; - buffer.write(&reloc_info.relocation(endian)); - } - } - } - - // Write symtab. - write_align(buffer, pointer_align); - debug_assert_eq!(symtab_offset, buffer.len()); - for index in local_symbols - .iter() - .copied() - .chain(external_symbols.iter().copied()) - .chain(undefined_symbols.iter().copied()) - { - let symbol = &self.symbols[index]; - // TODO: N_STAB - let (mut n_type, n_sect) = match symbol.section { - SymbolSection::Undefined => (macho::N_UNDF | macho::N_EXT, 0), - SymbolSection::Absolute => (macho::N_ABS, 0), - SymbolSection::Section(id) => (macho::N_SECT, id.0 + 1), - SymbolSection::None | SymbolSection::Common => { - return Err(Error(format!( - "unimplemented symbol `{}` section {:?}", - symbol.name().unwrap_or(""), - symbol.section - ))); - } - }; - match symbol.scope { - SymbolScope::Unknown | SymbolScope::Compilation => {} - SymbolScope::Linkage => { - n_type |= macho::N_EXT | macho::N_PEXT; - } - SymbolScope::Dynamic => { - n_type |= macho::N_EXT; - } - } - - let n_desc = if let SymbolFlags::MachO { n_desc } = symbol.flags { - n_desc - } else { - let mut n_desc = 0; - if symbol.weak { - if symbol.is_undefined() { - n_desc |= macho::N_WEAK_REF; - } else { - n_desc |= macho::N_WEAK_DEF; - } - } - n_desc - }; - - let n_value = match symbol.section.id() { - Some(section) => section_offsets[section.0].address + symbol.value, - None => symbol.value, - }; - - let n_strx = symbol_offsets[index] - .str_id - .map(|id| strtab.get_offset(id)) - .unwrap_or(0); - - macho.write_nlist( - buffer, - Nlist { - n_strx: n_strx as u32, - n_type, - n_sect: n_sect as u8, - n_desc, - n_value, - }, - ); - } - - // Write strtab. - debug_assert_eq!(strtab_offset, buffer.len()); - buffer.write_bytes(&strtab_data); - - debug_assert_eq!(offset, buffer.len()); - - Ok(()) - } -} - -struct MachHeader { - cputype: u32, - cpusubtype: u32, - filetype: u32, - ncmds: u32, - sizeofcmds: u32, - flags: u32, -} - -struct SegmentCommand { - cmdsize: u32, - segname: [u8; 16], - vmaddr: u64, - vmsize: u64, - fileoff: u64, - filesize: u64, - maxprot: u32, - initprot: u32, - nsects: u32, - flags: u32, -} - -pub struct SectionHeader { - sectname: [u8; 16], - segname: [u8; 16], - addr: u64, - size: u64, - offset: u32, - align: u32, - reloff: u32, - nreloc: u32, - flags: u32, -} - -struct Nlist { - n_strx: u32, - n_type: u8, - n_sect: u8, - n_desc: u16, - n_value: u64, -} - -trait MachO { - fn mach_header_size(&self) -> usize; - fn segment_command_size(&self) -> usize; - fn section_header_size(&self) -> usize; - fn nlist_size(&self) -> usize; - fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, section: MachHeader); - fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand); - fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader); - fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist); -} - -struct MachO32 { - endian: E, -} - -impl MachO for MachO32 { - fn mach_header_size(&self) -> usize { - mem::size_of::>() - } - - fn segment_command_size(&self) -> usize { - mem::size_of::>() - } - - fn section_header_size(&self) -> usize { - mem::size_of::>() - } - - fn nlist_size(&self) -> usize { - mem::size_of::>() - } - - fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) { - let endian = self.endian; - let magic = if endian.is_big_endian() { - macho::MH_MAGIC - } else { - macho::MH_CIGAM - }; - let header = macho::MachHeader32 { - magic: U32::new(BigEndian, magic), - cputype: U32::new(endian, header.cputype), - cpusubtype: U32::new(endian, header.cpusubtype), - filetype: U32::new(endian, header.filetype), - ncmds: U32::new(endian, header.ncmds), - sizeofcmds: U32::new(endian, header.sizeofcmds), - flags: U32::new(endian, header.flags), - }; - buffer.write(&header); - } - - fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) { - let endian = self.endian; - let segment = macho::SegmentCommand32 { - cmd: U32::new(endian, macho::LC_SEGMENT), - cmdsize: U32::new(endian, segment.cmdsize), - segname: segment.segname, - vmaddr: U32::new(endian, segment.vmaddr as u32), - vmsize: U32::new(endian, segment.vmsize as u32), - fileoff: U32::new(endian, segment.fileoff as u32), - filesize: U32::new(endian, segment.filesize as u32), - maxprot: U32::new(endian, segment.maxprot), - initprot: U32::new(endian, segment.initprot), - nsects: U32::new(endian, segment.nsects), - flags: U32::new(endian, segment.flags), - }; - buffer.write(&segment); - } - - fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) { - let endian = self.endian; - let section = macho::Section32 { - sectname: section.sectname, - segname: section.segname, - addr: U32::new(endian, section.addr as u32), - size: U32::new(endian, section.size as u32), - offset: U32::new(endian, section.offset), - align: U32::new(endian, section.align), - reloff: U32::new(endian, section.reloff), - nreloc: U32::new(endian, section.nreloc), - flags: U32::new(endian, section.flags), - reserved1: U32::default(), - reserved2: U32::default(), - }; - buffer.write(§ion); - } - - fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) { - let endian = self.endian; - let nlist = macho::Nlist32 { - n_strx: U32::new(endian, nlist.n_strx), - n_type: nlist.n_type, - n_sect: nlist.n_sect, - n_desc: U16::new(endian, nlist.n_desc), - n_value: U32::new(endian, nlist.n_value as u32), - }; - buffer.write(&nlist); - } -} - -struct MachO64 { - endian: E, -} - -impl MachO for MachO64 { - fn mach_header_size(&self) -> usize { - mem::size_of::>() - } - - fn segment_command_size(&self) -> usize { - mem::size_of::>() - } - - fn section_header_size(&self) -> usize { - mem::size_of::>() - } - - fn nlist_size(&self) -> usize { - mem::size_of::>() - } - - fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) { - let endian = self.endian; - let magic = if endian.is_big_endian() { - macho::MH_MAGIC_64 - } else { - macho::MH_CIGAM_64 - }; - let header = macho::MachHeader64 { - magic: U32::new(BigEndian, magic), - cputype: U32::new(endian, header.cputype), - cpusubtype: U32::new(endian, header.cpusubtype), - filetype: U32::new(endian, header.filetype), - ncmds: U32::new(endian, header.ncmds), - sizeofcmds: U32::new(endian, header.sizeofcmds), - flags: U32::new(endian, header.flags), - reserved: U32::default(), - }; - buffer.write(&header); - } - - fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) { - let endian = self.endian; - let segment = macho::SegmentCommand64 { - cmd: U32::new(endian, macho::LC_SEGMENT_64), - cmdsize: U32::new(endian, segment.cmdsize), - segname: segment.segname, - vmaddr: U64::new(endian, segment.vmaddr), - vmsize: U64::new(endian, segment.vmsize), - fileoff: U64::new(endian, segment.fileoff), - filesize: U64::new(endian, segment.filesize), - maxprot: U32::new(endian, segment.maxprot), - initprot: U32::new(endian, segment.initprot), - nsects: U32::new(endian, segment.nsects), - flags: U32::new(endian, segment.flags), - }; - buffer.write(&segment); - } - - fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) { - let endian = self.endian; - let section = macho::Section64 { - sectname: section.sectname, - segname: section.segname, - addr: U64::new(endian, section.addr), - size: U64::new(endian, section.size), - offset: U32::new(endian, section.offset), - align: U32::new(endian, section.align), - reloff: U32::new(endian, section.reloff), - nreloc: U32::new(endian, section.nreloc), - flags: U32::new(endian, section.flags), - reserved1: U32::default(), - reserved2: U32::default(), - reserved3: U32::default(), - }; - buffer.write(§ion); - } - - fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) { - let endian = self.endian; - let nlist = macho::Nlist64 { - n_strx: U32::new(endian, nlist.n_strx), - n_type: nlist.n_type, - n_sect: nlist.n_sect, - n_desc: U16::new(endian, nlist.n_desc), - n_value: U64Bytes::new(endian, nlist.n_value), - }; - buffer.write(&nlist); - } -} diff --git a/vendor/object/src/write/mod.rs b/vendor/object/src/write/mod.rs deleted file mode 100644 index cea4d2e..0000000 --- a/vendor/object/src/write/mod.rs +++ /dev/null @@ -1,961 +0,0 @@ -//! Interface for writing object files. - -use alloc::borrow::Cow; -use alloc::string::String; -use alloc::vec::Vec; -use core::{fmt, result, str}; -#[cfg(not(feature = "std"))] -use hashbrown::HashMap; -#[cfg(feature = "std")] -use std::{boxed::Box, collections::HashMap, error, io}; - -use crate::endian::{Endianness, U32, U64}; -use crate::{ - Architecture, BinaryFormat, ComdatKind, FileFlags, RelocationEncoding, RelocationKind, - SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, -}; - -#[cfg(feature = "coff")] -pub mod coff; -#[cfg(feature = "coff")] -pub use coff::CoffExportStyle; - -#[cfg(feature = "elf")] -pub mod elf; - -#[cfg(feature = "macho")] -mod macho; -#[cfg(feature = "macho")] -pub use macho::MachOBuildVersion; - -#[cfg(feature = "pe")] -pub mod pe; - -#[cfg(feature = "xcoff")] -mod xcoff; - -mod string; -pub use string::StringId; - -mod util; -pub use util::*; - -/// The error type used within the write module. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Error(String); - -impl fmt::Display for Error { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) - } -} - -#[cfg(feature = "std")] -impl error::Error for Error {} - -/// The result type used within the write module. -pub type Result = result::Result; - -/// A writable relocatable object file. -#[derive(Debug)] -pub struct Object<'a> { - format: BinaryFormat, - architecture: Architecture, - sub_architecture: Option, - endian: Endianness, - sections: Vec>, - standard_sections: HashMap, - symbols: Vec, - symbol_map: HashMap, SymbolId>, - stub_symbols: HashMap, - comdats: Vec, - /// File flags that are specific to each file format. - pub flags: FileFlags, - /// The symbol name mangling scheme. - pub mangling: Mangling, - /// Mach-O "_tlv_bootstrap" symbol. - tlv_bootstrap: Option, - /// Mach-O CPU subtype. - #[cfg(feature = "macho")] - macho_cpu_subtype: Option, - #[cfg(feature = "macho")] - macho_build_version: Option, -} - -impl<'a> Object<'a> { - /// Create an empty object file. - pub fn new(format: BinaryFormat, architecture: Architecture, endian: Endianness) -> Object<'a> { - Object { - format, - architecture, - sub_architecture: None, - endian, - sections: Vec::new(), - standard_sections: HashMap::new(), - symbols: Vec::new(), - symbol_map: HashMap::new(), - stub_symbols: HashMap::new(), - comdats: Vec::new(), - flags: FileFlags::None, - mangling: Mangling::default(format, architecture), - tlv_bootstrap: None, - #[cfg(feature = "macho")] - macho_cpu_subtype: None, - #[cfg(feature = "macho")] - macho_build_version: None, - } - } - - /// Return the file format. - #[inline] - pub fn format(&self) -> BinaryFormat { - self.format - } - - /// Return the architecture. - #[inline] - pub fn architecture(&self) -> Architecture { - self.architecture - } - - /// Return the sub-architecture. - #[inline] - pub fn sub_architecture(&self) -> Option { - self.sub_architecture - } - - /// Specify the sub-architecture. - pub fn set_sub_architecture(&mut self, sub_architecture: Option) { - self.sub_architecture = sub_architecture; - } - - /// Return the current mangling setting. - #[inline] - pub fn mangling(&self) -> Mangling { - self.mangling - } - - /// Specify the mangling setting. - #[inline] - pub fn set_mangling(&mut self, mangling: Mangling) { - self.mangling = mangling; - } - - /// Return the name for a standard segment. - /// - /// This will vary based on the file format. - #[allow(unused_variables)] - pub fn segment_name(&self, segment: StandardSegment) -> &'static [u8] { - match self.format { - #[cfg(feature = "coff")] - BinaryFormat::Coff => &[], - #[cfg(feature = "elf")] - BinaryFormat::Elf => &[], - #[cfg(feature = "macho")] - BinaryFormat::MachO => self.macho_segment_name(segment), - _ => unimplemented!(), - } - } - - /// Get the section with the given `SectionId`. - #[inline] - pub fn section(&self, section: SectionId) -> &Section<'a> { - &self.sections[section.0] - } - - /// Mutably get the section with the given `SectionId`. - #[inline] - pub fn section_mut(&mut self, section: SectionId) -> &mut Section<'a> { - &mut self.sections[section.0] - } - - /// Set the data for an existing section. - /// - /// Must not be called for sections that already have data, or that contain uninitialized data. - pub fn set_section_data(&mut self, section: SectionId, data: T, align: u64) - where - T: Into>, - { - self.sections[section.0].set_data(data, align) - } - - /// Append data to an existing section. Returns the section offset of the data. - pub fn append_section_data(&mut self, section: SectionId, data: &[u8], align: u64) -> u64 { - self.sections[section.0].append_data(data, align) - } - - /// Append zero-initialized data to an existing section. Returns the section offset of the data. - pub fn append_section_bss(&mut self, section: SectionId, size: u64, align: u64) -> u64 { - self.sections[section.0].append_bss(size, align) - } - - /// Return the `SectionId` of a standard section. - /// - /// If the section doesn't already exist then it is created. - pub fn section_id(&mut self, section: StandardSection) -> SectionId { - self.standard_sections - .get(§ion) - .cloned() - .unwrap_or_else(|| { - let (segment, name, kind, flags) = self.section_info(section); - let id = self.add_section(segment.to_vec(), name.to_vec(), kind); - self.section_mut(id).flags = flags; - id - }) - } - - /// Add a new section and return its `SectionId`. - /// - /// This also creates a section symbol. - pub fn add_section(&mut self, segment: Vec, name: Vec, kind: SectionKind) -> SectionId { - let id = SectionId(self.sections.len()); - self.sections.push(Section { - segment, - name, - kind, - size: 0, - align: 1, - data: Cow::Borrowed(&[]), - relocations: Vec::new(), - symbol: None, - flags: SectionFlags::None, - }); - - // Add to self.standard_sections if required. This may match multiple standard sections. - let section = &self.sections[id.0]; - for standard_section in StandardSection::all() { - if !self.standard_sections.contains_key(standard_section) { - let (segment, name, kind, _flags) = self.section_info(*standard_section); - if segment == &*section.segment && name == &*section.name && kind == section.kind { - self.standard_sections.insert(*standard_section, id); - } - } - } - - id - } - - fn section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match self.format { - #[cfg(feature = "coff")] - BinaryFormat::Coff => self.coff_section_info(section), - #[cfg(feature = "elf")] - BinaryFormat::Elf => self.elf_section_info(section), - #[cfg(feature = "macho")] - BinaryFormat::MachO => self.macho_section_info(section), - #[cfg(feature = "xcoff")] - BinaryFormat::Xcoff => self.xcoff_section_info(section), - _ => unimplemented!(), - } - } - - /// Add a subsection. Returns the `SectionId` and section offset of the data. - pub fn add_subsection( - &mut self, - section: StandardSection, - name: &[u8], - data: &[u8], - align: u64, - ) -> (SectionId, u64) { - let section_id = if self.has_subsections_via_symbols() { - self.set_subsections_via_symbols(); - self.section_id(section) - } else { - let (segment, name, kind, flags) = self.subsection_info(section, name); - let id = self.add_section(segment.to_vec(), name, kind); - self.section_mut(id).flags = flags; - id - }; - let offset = self.append_section_data(section_id, data, align); - (section_id, offset) - } - - fn has_subsections_via_symbols(&self) -> bool { - match self.format { - BinaryFormat::Coff | BinaryFormat::Elf | BinaryFormat::Xcoff => false, - BinaryFormat::MachO => true, - _ => unimplemented!(), - } - } - - fn set_subsections_via_symbols(&mut self) { - match self.format { - #[cfg(feature = "macho")] - BinaryFormat::MachO => self.macho_set_subsections_via_symbols(), - _ => unimplemented!(), - } - } - - fn subsection_info( - &self, - section: StandardSection, - value: &[u8], - ) -> (&'static [u8], Vec, SectionKind, SectionFlags) { - let (segment, section, kind, flags) = self.section_info(section); - let name = self.subsection_name(section, value); - (segment, name, kind, flags) - } - - #[allow(unused_variables)] - fn subsection_name(&self, section: &[u8], value: &[u8]) -> Vec { - debug_assert!(!self.has_subsections_via_symbols()); - match self.format { - #[cfg(feature = "coff")] - BinaryFormat::Coff => self.coff_subsection_name(section, value), - #[cfg(feature = "elf")] - BinaryFormat::Elf => self.elf_subsection_name(section, value), - _ => unimplemented!(), - } - } - - /// Get the COMDAT section group with the given `ComdatId`. - #[inline] - pub fn comdat(&self, comdat: ComdatId) -> &Comdat { - &self.comdats[comdat.0] - } - - /// Mutably get the COMDAT section group with the given `ComdatId`. - #[inline] - pub fn comdat_mut(&mut self, comdat: ComdatId) -> &mut Comdat { - &mut self.comdats[comdat.0] - } - - /// Add a new COMDAT section group and return its `ComdatId`. - pub fn add_comdat(&mut self, comdat: Comdat) -> ComdatId { - let comdat_id = ComdatId(self.comdats.len()); - self.comdats.push(comdat); - comdat_id - } - - /// Get the `SymbolId` of the symbol with the given name. - pub fn symbol_id(&self, name: &[u8]) -> Option { - self.symbol_map.get(name).cloned() - } - - /// Get the symbol with the given `SymbolId`. - #[inline] - pub fn symbol(&self, symbol: SymbolId) -> &Symbol { - &self.symbols[symbol.0] - } - - /// Mutably get the symbol with the given `SymbolId`. - #[inline] - pub fn symbol_mut(&mut self, symbol: SymbolId) -> &mut Symbol { - &mut self.symbols[symbol.0] - } - - /// Add a new symbol and return its `SymbolId`. - pub fn add_symbol(&mut self, mut symbol: Symbol) -> SymbolId { - // Defined symbols must have a scope. - debug_assert!(symbol.is_undefined() || symbol.scope != SymbolScope::Unknown); - if symbol.kind == SymbolKind::Section { - // There can only be one section symbol, but update its flags, since - // the automatically generated section symbol will have none. - let symbol_id = self.section_symbol(symbol.section.id().unwrap()); - if symbol.flags != SymbolFlags::None { - self.symbol_mut(symbol_id).flags = symbol.flags; - } - return symbol_id; - } - if !symbol.name.is_empty() - && (symbol.kind == SymbolKind::Text - || symbol.kind == SymbolKind::Data - || symbol.kind == SymbolKind::Tls) - { - let unmangled_name = symbol.name.clone(); - if let Some(prefix) = self.mangling.global_prefix() { - symbol.name.insert(0, prefix); - } - let symbol_id = self.add_raw_symbol(symbol); - self.symbol_map.insert(unmangled_name, symbol_id); - symbol_id - } else { - self.add_raw_symbol(symbol) - } - } - - fn add_raw_symbol(&mut self, symbol: Symbol) -> SymbolId { - let symbol_id = SymbolId(self.symbols.len()); - self.symbols.push(symbol); - symbol_id - } - - /// Return true if the file format supports `StandardSection::UninitializedTls`. - #[inline] - pub fn has_uninitialized_tls(&self) -> bool { - self.format != BinaryFormat::Coff - } - - /// Return true if the file format supports `StandardSection::Common`. - #[inline] - pub fn has_common(&self) -> bool { - self.format == BinaryFormat::MachO - } - - /// Add a new common symbol and return its `SymbolId`. - /// - /// For Mach-O, this appends the symbol to the `__common` section. - pub fn add_common_symbol(&mut self, mut symbol: Symbol, size: u64, align: u64) -> SymbolId { - if self.has_common() { - let symbol_id = self.add_symbol(symbol); - let section = self.section_id(StandardSection::Common); - self.add_symbol_bss(symbol_id, section, size, align); - symbol_id - } else { - symbol.section = SymbolSection::Common; - symbol.size = size; - self.add_symbol(symbol) - } - } - - /// Add a new file symbol and return its `SymbolId`. - pub fn add_file_symbol(&mut self, name: Vec) -> SymbolId { - self.add_raw_symbol(Symbol { - name, - value: 0, - size: 0, - kind: SymbolKind::File, - scope: SymbolScope::Compilation, - weak: false, - section: SymbolSection::None, - flags: SymbolFlags::None, - }) - } - - /// Get the symbol for a section. - pub fn section_symbol(&mut self, section_id: SectionId) -> SymbolId { - let section = &mut self.sections[section_id.0]; - if let Some(symbol) = section.symbol { - return symbol; - } - let name = if self.format == BinaryFormat::Coff { - section.name.clone() - } else { - Vec::new() - }; - let symbol_id = SymbolId(self.symbols.len()); - self.symbols.push(Symbol { - name, - value: 0, - size: 0, - kind: SymbolKind::Section, - scope: SymbolScope::Compilation, - weak: false, - section: SymbolSection::Section(section_id), - flags: SymbolFlags::None, - }); - section.symbol = Some(symbol_id); - symbol_id - } - - /// Append data to an existing section, and update a symbol to refer to it. - /// - /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the - /// symbol will indirectly point to the added data via the `__thread_vars` entry. - /// - /// Returns the section offset of the data. - pub fn add_symbol_data( - &mut self, - symbol_id: SymbolId, - section: SectionId, - data: &[u8], - align: u64, - ) -> u64 { - let offset = self.append_section_data(section, data, align); - self.set_symbol_data(symbol_id, section, offset, data.len() as u64); - offset - } - - /// Append zero-initialized data to an existing section, and update a symbol to refer to it. - /// - /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the - /// symbol will indirectly point to the added data via the `__thread_vars` entry. - /// - /// Returns the section offset of the data. - pub fn add_symbol_bss( - &mut self, - symbol_id: SymbolId, - section: SectionId, - size: u64, - align: u64, - ) -> u64 { - let offset = self.append_section_bss(section, size, align); - self.set_symbol_data(symbol_id, section, offset, size); - offset - } - - /// Update a symbol to refer to the given data within a section. - /// - /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the - /// symbol will indirectly point to the data via the `__thread_vars` entry. - #[allow(unused_mut)] - pub fn set_symbol_data( - &mut self, - mut symbol_id: SymbolId, - section: SectionId, - offset: u64, - size: u64, - ) { - // Defined symbols must have a scope. - debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown); - match self.format { - #[cfg(feature = "macho")] - BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id), - _ => {} - } - let symbol = self.symbol_mut(symbol_id); - symbol.value = offset; - symbol.size = size; - symbol.section = SymbolSection::Section(section); - } - - /// Convert a symbol to a section symbol and offset. - /// - /// Returns `None` if the symbol does not have a section. - pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> { - let symbol = self.symbol(symbol_id); - if symbol.kind == SymbolKind::Section { - return Some((symbol_id, 0)); - } - let symbol_offset = symbol.value; - let section = symbol.section.id()?; - let section_symbol = self.section_symbol(section); - Some((section_symbol, symbol_offset)) - } - - /// Add a relocation to a section. - /// - /// Relocations must only be added after the referenced symbols have been added - /// and defined (if applicable). - pub fn add_relocation(&mut self, section: SectionId, mut relocation: Relocation) -> Result<()> { - let addend = match self.format { - #[cfg(feature = "coff")] - BinaryFormat::Coff => self.coff_fixup_relocation(&mut relocation), - #[cfg(feature = "elf")] - BinaryFormat::Elf => self.elf_fixup_relocation(&mut relocation)?, - #[cfg(feature = "macho")] - BinaryFormat::MachO => self.macho_fixup_relocation(&mut relocation), - #[cfg(feature = "xcoff")] - BinaryFormat::Xcoff => self.xcoff_fixup_relocation(&mut relocation), - _ => unimplemented!(), - }; - if addend != 0 { - self.write_relocation_addend(section, &relocation, addend)?; - } - self.sections[section.0].relocations.push(relocation); - Ok(()) - } - - fn write_relocation_addend( - &mut self, - section: SectionId, - relocation: &Relocation, - addend: i64, - ) -> Result<()> { - let data = self.sections[section.0].data_mut(); - let offset = relocation.offset as usize; - match relocation.size { - 32 => data.write_at(offset, &U32::new(self.endian, addend as u32)), - 64 => data.write_at(offset, &U64::new(self.endian, addend as u64)), - _ => { - return Err(Error(format!( - "unimplemented relocation addend {:?}", - relocation - ))); - } - } - .map_err(|_| { - Error(format!( - "invalid relocation offset {}+{} (max {})", - relocation.offset, - relocation.size, - data.len() - )) - }) - } - - /// Write the object to a `Vec`. - pub fn write(&self) -> Result> { - let mut buffer = Vec::new(); - self.emit(&mut buffer)?; - Ok(buffer) - } - - /// Write the object to a `Write` implementation. - /// - /// Also flushes the writer. - /// - /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter) - /// instead of an unbuffered writer like [`File`](std::fs::File). - #[cfg(feature = "std")] - pub fn write_stream(&self, w: W) -> result::Result<(), Box> { - let mut stream = StreamingBuffer::new(w); - self.emit(&mut stream)?; - stream.result()?; - stream.into_inner().flush()?; - Ok(()) - } - - /// Write the object to a `WritableBuffer`. - pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - match self.format { - #[cfg(feature = "coff")] - BinaryFormat::Coff => self.coff_write(buffer), - #[cfg(feature = "elf")] - BinaryFormat::Elf => self.elf_write(buffer), - #[cfg(feature = "macho")] - BinaryFormat::MachO => self.macho_write(buffer), - #[cfg(feature = "xcoff")] - BinaryFormat::Xcoff => self.xcoff_write(buffer), - _ => unimplemented!(), - } - } -} - -/// A standard segment kind. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[non_exhaustive] -pub enum StandardSegment { - Text, - Data, - Debug, -} - -/// A standard section kind. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[non_exhaustive] -pub enum StandardSection { - Text, - Data, - ReadOnlyData, - ReadOnlyDataWithRel, - ReadOnlyString, - UninitializedData, - Tls, - /// Zero-fill TLS initializers. Unsupported for COFF. - UninitializedTls, - /// TLS variable structures. Only supported for Mach-O. - TlsVariables, - /// Common data. Only supported for Mach-O. - Common, - /// Notes for GNU properties. Only supported for ELF. - GnuProperty, -} - -impl StandardSection { - /// Return the section kind of a standard section. - pub fn kind(self) -> SectionKind { - match self { - StandardSection::Text => SectionKind::Text, - StandardSection::Data => SectionKind::Data, - StandardSection::ReadOnlyData => SectionKind::ReadOnlyData, - StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel, - StandardSection::ReadOnlyString => SectionKind::ReadOnlyString, - StandardSection::UninitializedData => SectionKind::UninitializedData, - StandardSection::Tls => SectionKind::Tls, - StandardSection::UninitializedTls => SectionKind::UninitializedTls, - StandardSection::TlsVariables => SectionKind::TlsVariables, - StandardSection::Common => SectionKind::Common, - StandardSection::GnuProperty => SectionKind::Note, - } - } - - // TODO: remembering to update this is error-prone, can we do better? - fn all() -> &'static [StandardSection] { - &[ - StandardSection::Text, - StandardSection::Data, - StandardSection::ReadOnlyData, - StandardSection::ReadOnlyDataWithRel, - StandardSection::ReadOnlyString, - StandardSection::UninitializedData, - StandardSection::Tls, - StandardSection::UninitializedTls, - StandardSection::TlsVariables, - StandardSection::Common, - StandardSection::GnuProperty, - ] - } -} - -/// An identifier used to reference a section. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SectionId(usize); - -/// A section in an object file. -#[derive(Debug)] -pub struct Section<'a> { - segment: Vec, - name: Vec, - kind: SectionKind, - size: u64, - align: u64, - data: Cow<'a, [u8]>, - relocations: Vec, - symbol: Option, - /// Section flags that are specific to each file format. - pub flags: SectionFlags, -} - -impl<'a> Section<'a> { - /// Try to convert the name to a utf8 string. - #[inline] - pub fn name(&self) -> Option<&str> { - str::from_utf8(&self.name).ok() - } - - /// Try to convert the segment to a utf8 string. - #[inline] - pub fn segment(&self) -> Option<&str> { - str::from_utf8(&self.segment).ok() - } - - /// Return true if this section contains zerofill data. - #[inline] - pub fn is_bss(&self) -> bool { - self.kind.is_bss() - } - - /// Set the data for a section. - /// - /// Must not be called for sections that already have data, or that contain uninitialized data. - pub fn set_data(&mut self, data: T, align: u64) - where - T: Into>, - { - debug_assert!(!self.is_bss()); - debug_assert_eq!(align & (align - 1), 0); - debug_assert!(self.data.is_empty()); - self.data = data.into(); - self.size = self.data.len() as u64; - self.align = align; - } - - /// Append data to a section. - /// - /// Must not be called for sections that contain uninitialized data. - pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 { - debug_assert!(!self.is_bss()); - debug_assert_eq!(align & (align - 1), 0); - if self.align < align { - self.align = align; - } - let align = align as usize; - let data = self.data.to_mut(); - let mut offset = data.len(); - if offset & (align - 1) != 0 { - offset += align - (offset & (align - 1)); - data.resize(offset, 0); - } - data.extend_from_slice(append_data); - self.size = data.len() as u64; - offset as u64 - } - - /// Append uninitialized data to a section. - /// - /// Must not be called for sections that contain initialized data. - pub fn append_bss(&mut self, size: u64, align: u64) -> u64 { - debug_assert!(self.is_bss()); - debug_assert_eq!(align & (align - 1), 0); - if self.align < align { - self.align = align; - } - let mut offset = self.size; - if offset & (align - 1) != 0 { - offset += align - (offset & (align - 1)); - self.size = offset; - } - self.size += size; - offset - } - - /// Returns the section as-built so far. - /// - /// This requires that the section is not a bss section. - pub fn data(&self) -> &[u8] { - debug_assert!(!self.is_bss()); - &self.data - } - - /// Returns the section as-built so far. - /// - /// This requires that the section is not a bss section. - pub fn data_mut(&mut self) -> &mut [u8] { - debug_assert!(!self.is_bss()); - self.data.to_mut() - } -} - -/// The section where a symbol is defined. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum SymbolSection { - /// The section is not applicable for this symbol (such as file symbols). - None, - /// The symbol is undefined. - Undefined, - /// The symbol has an absolute value. - Absolute, - /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions. - Common, - /// The symbol is defined in the given section. - Section(SectionId), -} - -impl SymbolSection { - /// Returns the section id for the section where the symbol is defined. - /// - /// May return `None` if the symbol is not defined in a section. - #[inline] - pub fn id(self) -> Option { - if let SymbolSection::Section(id) = self { - Some(id) - } else { - None - } - } -} - -/// An identifier used to reference a symbol. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SymbolId(usize); - -/// A symbol in an object file. -#[derive(Debug)] -pub struct Symbol { - /// The name of the symbol. - pub name: Vec, - /// The value of the symbol. - /// - /// If the symbol defined in a section, then this is the section offset of the symbol. - pub value: u64, - /// The size of the symbol. - pub size: u64, - /// The kind of the symbol. - pub kind: SymbolKind, - /// The scope of the symbol. - pub scope: SymbolScope, - /// Whether the symbol has weak binding. - pub weak: bool, - /// The section containing the symbol. - pub section: SymbolSection, - /// Symbol flags that are specific to each file format. - pub flags: SymbolFlags, -} - -impl Symbol { - /// Try to convert the name to a utf8 string. - #[inline] - pub fn name(&self) -> Option<&str> { - str::from_utf8(&self.name).ok() - } - - /// Return true if the symbol is undefined. - #[inline] - pub fn is_undefined(&self) -> bool { - self.section == SymbolSection::Undefined - } - - /// Return true if the symbol is common data. - /// - /// Note: does not check for `SymbolSection::Section` with `SectionKind::Common`. - #[inline] - pub fn is_common(&self) -> bool { - self.section == SymbolSection::Common - } - - /// Return true if the symbol scope is local. - #[inline] - pub fn is_local(&self) -> bool { - self.scope == SymbolScope::Compilation - } -} - -/// A relocation in an object file. -#[derive(Debug)] -pub struct Relocation { - /// The section offset of the place of the relocation. - pub offset: u64, - /// The size in bits of the place of relocation. - pub size: u8, - /// The operation used to calculate the result of the relocation. - pub kind: RelocationKind, - /// Information about how the result of the relocation operation is encoded in the place. - pub encoding: RelocationEncoding, - /// The symbol referred to by the relocation. - /// - /// This may be a section symbol. - pub symbol: SymbolId, - /// The addend to use in the relocation calculation. - /// - /// This may be in addition to an implicit addend stored at the place of the relocation. - pub addend: i64, -} - -/// An identifier used to reference a COMDAT section group. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ComdatId(usize); - -/// A COMDAT section group. -#[derive(Debug)] -pub struct Comdat { - /// The COMDAT selection kind. - /// - /// This determines the way in which the linker resolves multiple definitions of the COMDAT - /// sections. - pub kind: ComdatKind, - /// The COMDAT symbol. - /// - /// If this symbol is referenced, then all sections in the group will be included by the - /// linker. - pub symbol: SymbolId, - /// The sections in the group. - pub sections: Vec, -} - -/// The symbol name mangling scheme. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum Mangling { - /// No symbol mangling. - None, - /// Windows COFF symbol mangling. - Coff, - /// Windows COFF i386 symbol mangling. - CoffI386, - /// ELF symbol mangling. - Elf, - /// Mach-O symbol mangling. - MachO, - /// Xcoff symbol mangling. - Xcoff, -} - -impl Mangling { - /// Return the default symboling mangling for the given format and architecture. - pub fn default(format: BinaryFormat, architecture: Architecture) -> Self { - match (format, architecture) { - (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386, - (BinaryFormat::Coff, _) => Mangling::Coff, - (BinaryFormat::Elf, _) => Mangling::Elf, - (BinaryFormat::MachO, _) => Mangling::MachO, - (BinaryFormat::Xcoff, _) => Mangling::Xcoff, - _ => Mangling::None, - } - } - - /// Return the prefix to use for global symbols. - pub fn global_prefix(self) -> Option { - match self { - Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None, - Mangling::CoffI386 | Mangling::MachO => Some(b'_'), - } - } -} diff --git a/vendor/object/src/write/pe.rs b/vendor/object/src/write/pe.rs deleted file mode 100644 index 70da3a0..0000000 --- a/vendor/object/src/write/pe.rs +++ /dev/null @@ -1,847 +0,0 @@ -//! Helper for writing PE files. -use alloc::string::String; -use alloc::vec::Vec; -use core::mem; - -use crate::endian::{LittleEndian as LE, *}; -use crate::pe; -use crate::write::util; -use crate::write::{Error, Result, WritableBuffer}; - -/// A helper for writing PE files. -/// -/// Writing uses a two phase approach. The first phase reserves file ranges and virtual -/// address ranges for everything in the order that they will be written. -/// -/// The second phase writes everything out in order. Thus the caller must ensure writing -/// is in the same order that file ranges were reserved. -#[allow(missing_debug_implementations)] -pub struct Writer<'a> { - is_64: bool, - section_alignment: u32, - file_alignment: u32, - - buffer: &'a mut dyn WritableBuffer, - len: u32, - virtual_len: u32, - headers_len: u32, - - code_address: u32, - data_address: u32, - code_len: u32, - data_len: u32, - bss_len: u32, - - nt_headers_offset: u32, - data_directories: Vec, - section_header_num: u16, - sections: Vec
, - - symbol_offset: u32, - symbol_num: u32, - - reloc_blocks: Vec, - relocs: Vec>, - reloc_offset: u32, -} - -impl<'a> Writer<'a> { - /// Create a new `Writer`. - pub fn new( - is_64: bool, - section_alignment: u32, - file_alignment: u32, - buffer: &'a mut dyn WritableBuffer, - ) -> Self { - Writer { - is_64, - section_alignment, - file_alignment, - - buffer, - len: 0, - virtual_len: 0, - headers_len: 0, - - code_address: 0, - data_address: 0, - code_len: 0, - data_len: 0, - bss_len: 0, - - nt_headers_offset: 0, - data_directories: Vec::new(), - section_header_num: 0, - sections: Vec::new(), - - symbol_offset: 0, - symbol_num: 0, - - reloc_blocks: Vec::new(), - relocs: Vec::new(), - reloc_offset: 0, - } - } - - /// Return the current virtual address size that has been reserved. - /// - /// This is only valid after section headers have been reserved. - pub fn virtual_len(&self) -> u32 { - self.virtual_len - } - - /// Reserve a virtual address range with the given size. - /// - /// The reserved length will be increased to match the section alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve_virtual(&mut self, len: u32) -> u32 { - let offset = self.virtual_len; - self.virtual_len += len; - self.virtual_len = util::align_u32(self.virtual_len, self.section_alignment); - offset - } - - /// Reserve up to the given virtual address. - /// - /// The reserved length will be increased to match the section alignment. - pub fn reserve_virtual_until(&mut self, address: u32) { - debug_assert!(self.virtual_len <= address); - self.virtual_len = util::align_u32(address, self.section_alignment); - } - - /// Return the current file length that has been reserved. - pub fn reserved_len(&self) -> u32 { - self.len - } - - /// Return the current file length that has been written. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.buffer.len() - } - - /// Reserve a file range with the given size and starting alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve(&mut self, len: u32, align_start: u32) -> u32 { - if len == 0 { - return self.len; - } - self.reserve_align(align_start); - let offset = self.len; - self.len += len; - offset - } - - /// Reserve a file range with the given size and using the file alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve_file(&mut self, len: u32) -> u32 { - self.reserve(len, self.file_alignment) - } - - /// Write data. - pub fn write(&mut self, data: &[u8]) { - self.buffer.write_bytes(data); - } - - /// Reserve alignment padding bytes. - pub fn reserve_align(&mut self, align_start: u32) { - self.len = util::align_u32(self.len, align_start); - } - - /// Write alignment padding bytes. - pub fn write_align(&mut self, align_start: u32) { - util::write_align(self.buffer, align_start as usize); - } - - /// Write padding up to the next multiple of file alignment. - pub fn write_file_align(&mut self) { - self.write_align(self.file_alignment); - } - - /// Reserve the file range up to the given file offset. - pub fn reserve_until(&mut self, offset: u32) { - debug_assert!(self.len <= offset); - self.len = offset; - } - - /// Write padding up to the given file offset. - pub fn pad_until(&mut self, offset: u32) { - debug_assert!(self.buffer.len() <= offset as usize); - self.buffer.resize(offset as usize); - } - - /// Reserve the range for the DOS header. - /// - /// This must be at the start of the file. - /// - /// When writing, you may use `write_custom_dos_header` or `write_empty_dos_header`. - pub fn reserve_dos_header(&mut self) { - debug_assert_eq!(self.len, 0); - self.reserve(mem::size_of::() as u32, 1); - } - - /// Write a custom DOS header. - /// - /// This must be at the start of the file. - pub fn write_custom_dos_header(&mut self, dos_header: &pe::ImageDosHeader) -> Result<()> { - debug_assert_eq!(self.buffer.len(), 0); - - // Start writing. - self.buffer - .reserve(self.len as usize) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - self.buffer.write(dos_header); - Ok(()) - } - - /// Write the DOS header for a file without a stub. - /// - /// This must be at the start of the file. - /// - /// Uses default values for all fields. - pub fn write_empty_dos_header(&mut self) -> Result<()> { - self.write_custom_dos_header(&pe::ImageDosHeader { - e_magic: U16::new(LE, pe::IMAGE_DOS_SIGNATURE), - e_cblp: U16::new(LE, 0), - e_cp: U16::new(LE, 0), - e_crlc: U16::new(LE, 0), - e_cparhdr: U16::new(LE, 0), - e_minalloc: U16::new(LE, 0), - e_maxalloc: U16::new(LE, 0), - e_ss: U16::new(LE, 0), - e_sp: U16::new(LE, 0), - e_csum: U16::new(LE, 0), - e_ip: U16::new(LE, 0), - e_cs: U16::new(LE, 0), - e_lfarlc: U16::new(LE, 0), - e_ovno: U16::new(LE, 0), - e_res: [U16::new(LE, 0); 4], - e_oemid: U16::new(LE, 0), - e_oeminfo: U16::new(LE, 0), - e_res2: [U16::new(LE, 0); 10], - e_lfanew: U32::new(LE, self.nt_headers_offset), - }) - } - - /// Reserve a fixed DOS header and stub. - /// - /// Use `reserve_dos_header` and `reserve` if you need a custom stub. - pub fn reserve_dos_header_and_stub(&mut self) { - self.reserve_dos_header(); - self.reserve(64, 1); - } - - /// Write a fixed DOS header and stub. - /// - /// Use `write_custom_dos_header` and `write` if you need a custom stub. - pub fn write_dos_header_and_stub(&mut self) -> Result<()> { - self.write_custom_dos_header(&pe::ImageDosHeader { - e_magic: U16::new(LE, pe::IMAGE_DOS_SIGNATURE), - e_cblp: U16::new(LE, 0x90), - e_cp: U16::new(LE, 3), - e_crlc: U16::new(LE, 0), - e_cparhdr: U16::new(LE, 4), - e_minalloc: U16::new(LE, 0), - e_maxalloc: U16::new(LE, 0xffff), - e_ss: U16::new(LE, 0), - e_sp: U16::new(LE, 0xb8), - e_csum: U16::new(LE, 0), - e_ip: U16::new(LE, 0), - e_cs: U16::new(LE, 0), - e_lfarlc: U16::new(LE, 0x40), - e_ovno: U16::new(LE, 0), - e_res: [U16::new(LE, 0); 4], - e_oemid: U16::new(LE, 0), - e_oeminfo: U16::new(LE, 0), - e_res2: [U16::new(LE, 0); 10], - e_lfanew: U32::new(LE, self.nt_headers_offset), - })?; - - #[rustfmt::skip] - self.buffer.write_bytes(&[ - 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, - 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, - 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, - 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]); - - Ok(()) - } - - fn nt_headers_size(&self) -> u32 { - if self.is_64 { - mem::size_of::() as u32 - } else { - mem::size_of::() as u32 - } - } - - fn optional_header_size(&self) -> u32 { - let size = if self.is_64 { - mem::size_of::() as u32 - } else { - mem::size_of::() as u32 - }; - size + self.data_directories.len() as u32 * mem::size_of::() as u32 - } - - /// Return the offset of the NT headers, if reserved. - pub fn nt_headers_offset(&self) -> u32 { - self.nt_headers_offset - } - - /// Reserve the range for the NT headers. - pub fn reserve_nt_headers(&mut self, data_directory_num: usize) { - debug_assert_eq!(self.nt_headers_offset, 0); - self.nt_headers_offset = self.reserve(self.nt_headers_size(), 8); - self.data_directories = vec![DataDirectory::default(); data_directory_num]; - self.reserve( - data_directory_num as u32 * mem::size_of::() as u32, - 1, - ); - } - - /// Set the virtual address and size of a data directory. - pub fn set_data_directory(&mut self, index: usize, virtual_address: u32, size: u32) { - self.data_directories[index] = DataDirectory { - virtual_address, - size, - } - } - - /// Write the NT headers. - pub fn write_nt_headers(&mut self, nt_headers: NtHeaders) { - self.pad_until(self.nt_headers_offset); - self.buffer.write(&U32::new(LE, pe::IMAGE_NT_SIGNATURE)); - let file_header = pe::ImageFileHeader { - machine: U16::new(LE, nt_headers.machine), - number_of_sections: U16::new(LE, self.section_header_num), - time_date_stamp: U32::new(LE, nt_headers.time_date_stamp), - pointer_to_symbol_table: U32::new(LE, self.symbol_offset), - number_of_symbols: U32::new(LE, self.symbol_num), - size_of_optional_header: U16::new(LE, self.optional_header_size() as u16), - characteristics: U16::new(LE, nt_headers.characteristics), - }; - self.buffer.write(&file_header); - if self.is_64 { - let optional_header = pe::ImageOptionalHeader64 { - magic: U16::new(LE, pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC), - major_linker_version: nt_headers.major_linker_version, - minor_linker_version: nt_headers.minor_linker_version, - size_of_code: U32::new(LE, self.code_len), - size_of_initialized_data: U32::new(LE, self.data_len), - size_of_uninitialized_data: U32::new(LE, self.bss_len), - address_of_entry_point: U32::new(LE, nt_headers.address_of_entry_point), - base_of_code: U32::new(LE, self.code_address), - image_base: U64::new(LE, nt_headers.image_base), - section_alignment: U32::new(LE, self.section_alignment), - file_alignment: U32::new(LE, self.file_alignment), - major_operating_system_version: U16::new( - LE, - nt_headers.major_operating_system_version, - ), - minor_operating_system_version: U16::new( - LE, - nt_headers.minor_operating_system_version, - ), - major_image_version: U16::new(LE, nt_headers.major_image_version), - minor_image_version: U16::new(LE, nt_headers.minor_image_version), - major_subsystem_version: U16::new(LE, nt_headers.major_subsystem_version), - minor_subsystem_version: U16::new(LE, nt_headers.minor_subsystem_version), - win32_version_value: U32::new(LE, 0), - size_of_image: U32::new(LE, self.virtual_len), - size_of_headers: U32::new(LE, self.headers_len), - check_sum: U32::new(LE, 0), - subsystem: U16::new(LE, nt_headers.subsystem), - dll_characteristics: U16::new(LE, nt_headers.dll_characteristics), - size_of_stack_reserve: U64::new(LE, nt_headers.size_of_stack_reserve), - size_of_stack_commit: U64::new(LE, nt_headers.size_of_stack_commit), - size_of_heap_reserve: U64::new(LE, nt_headers.size_of_heap_reserve), - size_of_heap_commit: U64::new(LE, nt_headers.size_of_heap_commit), - loader_flags: U32::new(LE, 0), - number_of_rva_and_sizes: U32::new(LE, self.data_directories.len() as u32), - }; - self.buffer.write(&optional_header); - } else { - let optional_header = pe::ImageOptionalHeader32 { - magic: U16::new(LE, pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC), - major_linker_version: nt_headers.major_linker_version, - minor_linker_version: nt_headers.minor_linker_version, - size_of_code: U32::new(LE, self.code_len), - size_of_initialized_data: U32::new(LE, self.data_len), - size_of_uninitialized_data: U32::new(LE, self.bss_len), - address_of_entry_point: U32::new(LE, nt_headers.address_of_entry_point), - base_of_code: U32::new(LE, self.code_address), - base_of_data: U32::new(LE, self.data_address), - image_base: U32::new(LE, nt_headers.image_base as u32), - section_alignment: U32::new(LE, self.section_alignment), - file_alignment: U32::new(LE, self.file_alignment), - major_operating_system_version: U16::new( - LE, - nt_headers.major_operating_system_version, - ), - minor_operating_system_version: U16::new( - LE, - nt_headers.minor_operating_system_version, - ), - major_image_version: U16::new(LE, nt_headers.major_image_version), - minor_image_version: U16::new(LE, nt_headers.minor_image_version), - major_subsystem_version: U16::new(LE, nt_headers.major_subsystem_version), - minor_subsystem_version: U16::new(LE, nt_headers.minor_subsystem_version), - win32_version_value: U32::new(LE, 0), - size_of_image: U32::new(LE, self.virtual_len), - size_of_headers: U32::new(LE, self.headers_len), - check_sum: U32::new(LE, 0), - subsystem: U16::new(LE, nt_headers.subsystem), - dll_characteristics: U16::new(LE, nt_headers.dll_characteristics), - size_of_stack_reserve: U32::new(LE, nt_headers.size_of_stack_reserve as u32), - size_of_stack_commit: U32::new(LE, nt_headers.size_of_stack_commit as u32), - size_of_heap_reserve: U32::new(LE, nt_headers.size_of_heap_reserve as u32), - size_of_heap_commit: U32::new(LE, nt_headers.size_of_heap_commit as u32), - loader_flags: U32::new(LE, 0), - number_of_rva_and_sizes: U32::new(LE, self.data_directories.len() as u32), - }; - self.buffer.write(&optional_header); - } - - for dir in &self.data_directories { - self.buffer.write(&pe::ImageDataDirectory { - virtual_address: U32::new(LE, dir.virtual_address), - size: U32::new(LE, dir.size), - }) - } - } - - /// Reserve the section headers. - /// - /// The number of reserved section headers must be the same as the number of sections that - /// are later reserved. - // TODO: change this to a maximum number of sections? - pub fn reserve_section_headers(&mut self, section_header_num: u16) { - debug_assert_eq!(self.section_header_num, 0); - self.section_header_num = section_header_num; - self.reserve( - u32::from(section_header_num) * mem::size_of::() as u32, - 1, - ); - // Padding before sections must be included in headers_len. - self.reserve_align(self.file_alignment); - self.headers_len = self.len; - self.reserve_virtual(self.len); - } - - /// Write the section headers. - /// - /// This uses information that was recorded when the sections were reserved. - pub fn write_section_headers(&mut self) { - debug_assert_eq!(self.section_header_num as usize, self.sections.len()); - for section in &self.sections { - let section_header = pe::ImageSectionHeader { - name: section.name, - virtual_size: U32::new(LE, section.range.virtual_size), - virtual_address: U32::new(LE, section.range.virtual_address), - size_of_raw_data: U32::new(LE, section.range.file_size), - pointer_to_raw_data: U32::new(LE, section.range.file_offset), - pointer_to_relocations: U32::new(LE, 0), - pointer_to_linenumbers: U32::new(LE, 0), - number_of_relocations: U16::new(LE, 0), - number_of_linenumbers: U16::new(LE, 0), - characteristics: U32::new(LE, section.characteristics), - }; - self.buffer.write(§ion_header); - } - } - - /// Reserve a section. - /// - /// Returns the file range and virtual address range that are reserved - /// for the section. - pub fn reserve_section( - &mut self, - name: [u8; 8], - characteristics: u32, - virtual_size: u32, - data_size: u32, - ) -> SectionRange { - let virtual_address = self.reserve_virtual(virtual_size); - - // Padding after section must be included in section file size. - let file_size = util::align_u32(data_size, self.file_alignment); - let file_offset = if file_size != 0 { - self.reserve(file_size, self.file_alignment) - } else { - 0 - }; - - // Sizes in optional header use the virtual size with the file alignment. - let aligned_virtual_size = util::align_u32(virtual_size, self.file_alignment); - if characteristics & pe::IMAGE_SCN_CNT_CODE != 0 { - if self.code_address == 0 { - self.code_address = virtual_address; - } - self.code_len += aligned_virtual_size; - } else if characteristics & pe::IMAGE_SCN_CNT_INITIALIZED_DATA != 0 { - if self.data_address == 0 { - self.data_address = virtual_address; - } - self.data_len += aligned_virtual_size; - } else if characteristics & pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 { - if self.data_address == 0 { - self.data_address = virtual_address; - } - self.bss_len += aligned_virtual_size; - } - - let range = SectionRange { - virtual_address, - virtual_size, - file_offset, - file_size, - }; - self.sections.push(Section { - name, - characteristics, - range, - }); - range - } - - /// Write the data for a section. - pub fn write_section(&mut self, offset: u32, data: &[u8]) { - if data.is_empty() { - return; - } - self.pad_until(offset); - self.write(data); - self.write_align(self.file_alignment); - } - - /// Reserve a `.text` section. - /// - /// Contains executable code. - pub fn reserve_text_section(&mut self, size: u32) -> SectionRange { - self.reserve_section( - *b".text\0\0\0", - pe::IMAGE_SCN_CNT_CODE | pe::IMAGE_SCN_MEM_EXECUTE | pe::IMAGE_SCN_MEM_READ, - size, - size, - ) - } - - /// Reserve a `.data` section. - /// - /// Contains initialized data. - /// - /// May also contain uninitialized data if `virtual_size` is greater than `data_size`. - pub fn reserve_data_section(&mut self, virtual_size: u32, data_size: u32) -> SectionRange { - self.reserve_section( - *b".data\0\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ | pe::IMAGE_SCN_MEM_WRITE, - virtual_size, - data_size, - ) - } - - /// Reserve a `.rdata` section. - /// - /// Contains read-only initialized data. - pub fn reserve_rdata_section(&mut self, size: u32) -> SectionRange { - self.reserve_section( - *b".rdata\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ, - size, - size, - ) - } - - /// Reserve a `.bss` section. - /// - /// Contains uninitialized data. - pub fn reserve_bss_section(&mut self, size: u32) -> SectionRange { - self.reserve_section( - *b".bss\0\0\0\0", - pe::IMAGE_SCN_CNT_UNINITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ | pe::IMAGE_SCN_MEM_WRITE, - size, - 0, - ) - } - - /// Reserve an `.idata` section. - /// - /// Contains import tables. Note that it is permissible to store import tables in a different - /// section. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_IMPORT` data directory. - pub fn reserve_idata_section(&mut self, size: u32) -> SectionRange { - let range = self.reserve_section( - *b".idata\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ | pe::IMAGE_SCN_MEM_WRITE, - size, - size, - ); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_IMPORT]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: range.virtual_address, - size, - }; - range - } - - /// Reserve an `.edata` section. - /// - /// Contains export tables. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_EXPORT` data directory. - pub fn reserve_edata_section(&mut self, size: u32) -> SectionRange { - let range = self.reserve_section( - *b".edata\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ, - size, - size, - ); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_EXPORT]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: range.virtual_address, - size, - }; - range - } - - /// Reserve a `.pdata` section. - /// - /// Contains exception information. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_EXCEPTION` data directory. - pub fn reserve_pdata_section(&mut self, size: u32) -> SectionRange { - let range = self.reserve_section( - *b".pdata\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ, - size, - size, - ); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_EXCEPTION]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: range.virtual_address, - size, - }; - range - } - - /// Reserve a `.xdata` section. - /// - /// Contains exception information. - pub fn reserve_xdata_section(&mut self, size: u32) -> SectionRange { - self.reserve_section( - *b".xdata\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ, - size, - size, - ) - } - - /// Reserve a `.rsrc` section. - /// - /// Contains the resource directory. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_RESOURCE` data directory. - pub fn reserve_rsrc_section(&mut self, size: u32) -> SectionRange { - let range = self.reserve_section( - *b".rsrc\0\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA | pe::IMAGE_SCN_MEM_READ, - size, - size, - ); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_RESOURCE]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: range.virtual_address, - size, - }; - range - } - - /// Add a base relocation. - /// - /// `typ` must be one of the `IMAGE_REL_BASED_*` constants. - pub fn add_reloc(&mut self, mut virtual_address: u32, typ: u16) { - let reloc = U16::new(LE, typ << 12 | (virtual_address & 0xfff) as u16); - virtual_address &= !0xfff; - if let Some(block) = self.reloc_blocks.last_mut() { - if block.virtual_address == virtual_address { - self.relocs.push(reloc); - block.count += 1; - return; - } - // Blocks must have an even number of relocations. - if block.count & 1 != 0 { - self.relocs.push(U16::new(LE, 0)); - block.count += 1; - } - debug_assert!(block.virtual_address < virtual_address); - } - self.relocs.push(reloc); - self.reloc_blocks.push(RelocBlock { - virtual_address, - count: 1, - }); - } - - /// Return true if a base relocation has been added. - pub fn has_relocs(&mut self) -> bool { - !self.relocs.is_empty() - } - - /// Reserve a `.reloc` section. - /// - /// This contains the base relocations that were added with `add_reloc`. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_BASERELOC` data directory. - pub fn reserve_reloc_section(&mut self) -> SectionRange { - if let Some(block) = self.reloc_blocks.last_mut() { - // Blocks must have an even number of relocations. - if block.count & 1 != 0 { - self.relocs.push(U16::new(LE, 0)); - block.count += 1; - } - } - let size = self.reloc_blocks.iter().map(RelocBlock::size).sum(); - let range = self.reserve_section( - *b".reloc\0\0", - pe::IMAGE_SCN_CNT_INITIALIZED_DATA - | pe::IMAGE_SCN_MEM_READ - | pe::IMAGE_SCN_MEM_DISCARDABLE, - size, - size, - ); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_BASERELOC]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: range.virtual_address, - size, - }; - self.reloc_offset = range.file_offset; - range - } - - /// Write a `.reloc` section. - /// - /// This contains the base relocations that were added with `add_reloc`. - pub fn write_reloc_section(&mut self) { - if self.reloc_offset == 0 { - return; - } - self.pad_until(self.reloc_offset); - - let mut total = 0; - for block in &self.reloc_blocks { - self.buffer.write(&pe::ImageBaseRelocation { - virtual_address: U32::new(LE, block.virtual_address), - size_of_block: U32::new(LE, block.size()), - }); - self.buffer - .write_slice(&self.relocs[total..][..block.count as usize]); - total += block.count as usize; - } - debug_assert_eq!(total, self.relocs.len()); - - self.write_align(self.file_alignment); - } - - /// Reserve the certificate table. - /// - /// This also sets the `pe::IMAGE_DIRECTORY_ENTRY_SECURITY` data directory. - // TODO: reserve individual certificates - pub fn reserve_certificate_table(&mut self, size: u32) { - let size = util::align_u32(size, 8); - let offset = self.reserve(size, 8); - let dir = &mut self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_SECURITY]; - debug_assert_eq!(dir.virtual_address, 0); - *dir = DataDirectory { - virtual_address: offset, - size, - }; - } - - /// Write the certificate table. - // TODO: write individual certificates - pub fn write_certificate_table(&mut self, data: &[u8]) { - let dir = self.data_directories[pe::IMAGE_DIRECTORY_ENTRY_SECURITY]; - self.pad_until(dir.virtual_address); - self.write(data); - self.pad_until(dir.virtual_address + dir.size); - } -} - -/// Information required for writing [`pe::ImageNtHeaders32`] or [`pe::ImageNtHeaders64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct NtHeaders { - // ImageFileHeader - pub machine: u16, - pub time_date_stamp: u32, - pub characteristics: u16, - // ImageOptionalHeader - pub major_linker_version: u8, - pub minor_linker_version: u8, - pub address_of_entry_point: u32, - pub image_base: u64, - pub major_operating_system_version: u16, - pub minor_operating_system_version: u16, - pub major_image_version: u16, - pub minor_image_version: u16, - pub major_subsystem_version: u16, - pub minor_subsystem_version: u16, - pub subsystem: u16, - pub dll_characteristics: u16, - pub size_of_stack_reserve: u64, - pub size_of_stack_commit: u64, - pub size_of_heap_reserve: u64, - pub size_of_heap_commit: u64, -} - -#[derive(Default, Clone, Copy)] -struct DataDirectory { - virtual_address: u32, - size: u32, -} - -/// Information required for writing [`pe::ImageSectionHeader`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Section { - pub name: [u8; pe::IMAGE_SIZEOF_SHORT_NAME], - pub characteristics: u32, - pub range: SectionRange, -} - -/// The file range and virtual address range for a section. -#[allow(missing_docs)] -#[derive(Debug, Default, Clone, Copy)] -pub struct SectionRange { - pub virtual_address: u32, - pub virtual_size: u32, - pub file_offset: u32, - pub file_size: u32, -} - -struct RelocBlock { - virtual_address: u32, - count: u32, -} - -impl RelocBlock { - fn size(&self) -> u32 { - mem::size_of::() as u32 + self.count * mem::size_of::() as u32 - } -} diff --git a/vendor/object/src/write/string.rs b/vendor/object/src/write/string.rs deleted file mode 100644 index b23274a..0000000 --- a/vendor/object/src/write/string.rs +++ /dev/null @@ -1,159 +0,0 @@ -use alloc::vec::Vec; - -#[cfg(feature = "std")] -type IndexSet = indexmap::IndexSet; -#[cfg(not(feature = "std"))] -type IndexSet = indexmap::IndexSet; - -/// An identifier for an entry in a string table. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct StringId(usize); - -#[derive(Debug, Default)] -pub(crate) struct StringTable<'a> { - strings: IndexSet<&'a [u8]>, - offsets: Vec, -} - -impl<'a> StringTable<'a> { - /// Add a string to the string table. - /// - /// Panics if the string table has already been written, or - /// if the string contains a null byte. - pub fn add(&mut self, string: &'a [u8]) -> StringId { - assert!(self.offsets.is_empty()); - assert!(!string.contains(&0)); - let id = self.strings.insert_full(string).0; - StringId(id) - } - - /// Return the id of the given string. - /// - /// Panics if the string is not in the string table. - pub fn get_id(&self, string: &[u8]) -> StringId { - let id = self.strings.get_index_of(string).unwrap(); - StringId(id) - } - - /// Return the string for the given id. - /// - /// Panics if the string is not in the string table. - pub fn get_string(&self, id: StringId) -> &'a [u8] { - self.strings.get_index(id.0).unwrap() - } - - /// Return the offset of the given string. - /// - /// Panics if the string table has not been written, or - /// if the string is not in the string table. - pub fn get_offset(&self, id: StringId) -> usize { - self.offsets[id.0] - } - - /// Append the string table to the given `Vec`, and - /// calculate the list of string offsets. - /// - /// `base` is the initial string table offset. For example, - /// this should be 1 for ELF, to account for the initial - /// null byte (which must have been written by the caller). - pub fn write(&mut self, base: usize, w: &mut Vec) { - assert!(self.offsets.is_empty()); - - let mut ids: Vec<_> = (0..self.strings.len()).collect(); - sort(&mut ids, 1, &self.strings); - - self.offsets = vec![0; ids.len()]; - let mut offset = base; - let mut previous = &[][..]; - for id in ids { - let string = self.strings.get_index(id).unwrap(); - if previous.ends_with(string) { - self.offsets[id] = offset - string.len() - 1; - } else { - self.offsets[id] = offset; - w.extend_from_slice(string); - w.push(0); - offset += string.len() + 1; - previous = string; - } - } - } -} - -// Multi-key quicksort. -// -// Ordering is such that if a string is a suffix of at least one other string, -// then it is placed immediately after one of those strings. That is: -// - comparison starts at the end of the string -// - shorter strings come later -// -// Based on the implementation in LLVM. -fn sort(mut ids: &mut [usize], mut pos: usize, strings: &IndexSet<&[u8]>) { - loop { - if ids.len() <= 1 { - return; - } - - let pivot = byte(ids[0], pos, strings); - let mut lower = 0; - let mut upper = ids.len(); - let mut i = 1; - while i < upper { - let b = byte(ids[i], pos, strings); - if b > pivot { - ids.swap(lower, i); - lower += 1; - i += 1; - } else if b < pivot { - upper -= 1; - ids.swap(upper, i); - } else { - i += 1; - } - } - - sort(&mut ids[..lower], pos, strings); - sort(&mut ids[upper..], pos, strings); - - if pivot == 0 { - return; - } - ids = &mut ids[lower..upper]; - pos += 1; - } -} - -fn byte(id: usize, pos: usize, strings: &IndexSet<&[u8]>) -> u8 { - let string = strings.get_index(id).unwrap(); - let len = string.len(); - if len >= pos { - string[len - pos] - } else { - // We know the strings don't contain null bytes. - 0 - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn string_table() { - let mut table = StringTable::default(); - let id0 = table.add(b""); - let id1 = table.add(b"foo"); - let id2 = table.add(b"bar"); - let id3 = table.add(b"foobar"); - - let mut data = Vec::new(); - data.push(0); - table.write(1, &mut data); - assert_eq!(data, b"\0foobar\0foo\0"); - - assert_eq!(table.get_offset(id0), 11); - assert_eq!(table.get_offset(id1), 8); - assert_eq!(table.get_offset(id2), 4); - assert_eq!(table.get_offset(id3), 1); - } -} diff --git a/vendor/object/src/write/util.rs b/vendor/object/src/write/util.rs deleted file mode 100644 index f7ee2f4..0000000 --- a/vendor/object/src/write/util.rs +++ /dev/null @@ -1,260 +0,0 @@ -use alloc::vec::Vec; -#[cfg(feature = "std")] -use std::{io, mem}; - -use crate::pod::{bytes_of, bytes_of_slice, Pod}; - -/// Trait for writable buffer. -#[allow(clippy::len_without_is_empty)] -pub trait WritableBuffer { - /// Returns position/offset for data to be written at. - /// - /// Should only be used in debug assertions - fn len(&self) -> usize; - - /// Reserves specified number of bytes in the buffer. - /// - /// This will be called exactly once before writing anything to the buffer, - /// and the given size is the exact total number of bytes that will be written. - fn reserve(&mut self, size: usize) -> Result<(), ()>; - - /// Writes zero bytes at the end of the buffer until the buffer - /// has the specified length. - fn resize(&mut self, new_len: usize); - - /// Writes the specified slice of bytes at the end of the buffer. - fn write_bytes(&mut self, val: &[u8]); - - /// Writes the specified `Pod` type at the end of the buffer. - fn write_pod(&mut self, val: &T) - where - Self: Sized, - { - self.write_bytes(bytes_of(val)) - } - - /// Writes the specified `Pod` slice at the end of the buffer. - fn write_pod_slice(&mut self, val: &[T]) - where - Self: Sized, - { - self.write_bytes(bytes_of_slice(val)) - } -} - -impl<'a> dyn WritableBuffer + 'a { - /// Writes the specified `Pod` type at the end of the buffer. - pub fn write(&mut self, val: &T) { - self.write_bytes(bytes_of(val)) - } - - /// Writes the specified `Pod` slice at the end of the buffer. - pub fn write_slice(&mut self, val: &[T]) { - self.write_bytes(bytes_of_slice(val)) - } -} - -impl WritableBuffer for Vec { - #[inline] - fn len(&self) -> usize { - self.len() - } - - #[inline] - fn reserve(&mut self, size: usize) -> Result<(), ()> { - debug_assert!(self.is_empty()); - self.reserve(size); - Ok(()) - } - - #[inline] - fn resize(&mut self, new_len: usize) { - debug_assert!(new_len >= self.len()); - self.resize(new_len, 0); - } - - #[inline] - fn write_bytes(&mut self, val: &[u8]) { - debug_assert!(self.len() + val.len() <= self.capacity()); - self.extend_from_slice(val) - } -} - -/// A [`WritableBuffer`] that streams data to a [`Write`](std::io::Write) implementation. -/// -/// [`Self::result`] must be called to determine if an I/O error occurred during writing. -/// -/// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter) -/// instead of an unbuffered writer like [`File`](std::fs::File). -#[cfg(feature = "std")] -#[derive(Debug)] -pub struct StreamingBuffer { - writer: W, - len: usize, - result: Result<(), io::Error>, -} - -#[cfg(feature = "std")] -impl StreamingBuffer { - /// Create a new `StreamingBuffer` backed by the given writer. - pub fn new(writer: W) -> Self { - StreamingBuffer { - writer, - len: 0, - result: Ok(()), - } - } - - /// Unwraps this [`StreamingBuffer`] giving back the original writer. - pub fn into_inner(self) -> W { - self.writer - } - - /// Returns any error that occurred during writing. - pub fn result(&mut self) -> Result<(), io::Error> { - mem::replace(&mut self.result, Ok(())) - } -} - -#[cfg(feature = "std")] -impl WritableBuffer for StreamingBuffer { - #[inline] - fn len(&self) -> usize { - self.len - } - - #[inline] - fn reserve(&mut self, _size: usize) -> Result<(), ()> { - Ok(()) - } - - #[inline] - fn resize(&mut self, new_len: usize) { - debug_assert!(self.len <= new_len); - while self.len < new_len { - let write_amt = (new_len - self.len - 1) % 1024 + 1; - self.write_bytes(&[0; 1024][..write_amt]); - } - } - - #[inline] - fn write_bytes(&mut self, val: &[u8]) { - if self.result.is_ok() { - self.result = self.writer.write_all(val); - } - self.len += val.len(); - } -} - -/// A trait for mutable byte slices. -/// -/// It provides convenience methods for `Pod` types. -pub(crate) trait BytesMut { - fn write_at(self, offset: usize, val: &T) -> Result<(), ()>; -} - -impl<'a> BytesMut for &'a mut [u8] { - #[inline] - fn write_at(self, offset: usize, val: &T) -> Result<(), ()> { - let src = bytes_of(val); - let dest = self.get_mut(offset..).ok_or(())?; - let dest = dest.get_mut(..src.len()).ok_or(())?; - dest.copy_from_slice(src); - Ok(()) - } -} - -/// Write an unsigned number using the LEB128 encoding to a buffer. -/// -/// Returns the number of bytes written. -pub(crate) fn write_uleb128(buf: &mut Vec, mut val: u64) -> usize { - let mut len = 0; - loop { - let mut byte = (val & 0x7f) as u8; - val >>= 7; - let done = val == 0; - if !done { - byte |= 0x80; - } - - buf.push(byte); - len += 1; - - if done { - return len; - } - } -} - -/// Write a signed number using the LEB128 encoding to a buffer. -/// -/// Returns the number of bytes written. -#[allow(dead_code)] -pub(crate) fn write_sleb128(buf: &mut Vec, mut val: i64) -> usize { - let mut len = 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 &= !0x80; - } else { - // Remove the sign bit - val >>= 1; - byte |= 0x80; - } - - buf.push(byte); - len += 1; - - if done { - return len; - } - } -} - -pub(crate) fn align(offset: usize, size: usize) -> usize { - (offset + (size - 1)) & !(size - 1) -} - -#[allow(dead_code)] -pub(crate) fn align_u32(offset: u32, size: u32) -> u32 { - (offset + (size - 1)) & !(size - 1) -} - -#[allow(dead_code)] -pub(crate) fn align_u64(offset: u64, size: u64) -> u64 { - (offset + (size - 1)) & !(size - 1) -} - -pub(crate) fn write_align(buffer: &mut dyn WritableBuffer, size: usize) { - let new_len = align(buffer.len(), size); - buffer.resize(new_len); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn bytes_mut() { - let data = vec![0x01, 0x23, 0x45, 0x67]; - - let mut bytes = data.clone(); - bytes.extend_from_slice(bytes_of(&u16::to_be(0x89ab))); - assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]); - - let mut bytes = data.clone(); - assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(())); - assert_eq!(bytes, [0x89, 0xab, 0x45, 0x67]); - - let mut bytes = data.clone(); - assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(())); - assert_eq!(bytes, [0x01, 0x23, 0x89, 0xab]); - - assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(())); - assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(())); - assert_eq!(vec![].write_at(0, &u32::to_be(0x89ab)), Err(())); - } -} diff --git a/vendor/object/src/write/xcoff.rs b/vendor/object/src/write/xcoff.rs deleted file mode 100644 index fc58886..0000000 --- a/vendor/object/src/write/xcoff.rs +++ /dev/null @@ -1,556 +0,0 @@ -use core::mem; - -use crate::endian::{BigEndian as BE, I16, U16, U32}; -use crate::write::string::*; -use crate::write::util::*; -use crate::write::*; - -use crate::{xcoff, AddressSize}; - -#[derive(Default, Clone, Copy)] -struct SectionOffsets { - address: u64, - data_offset: usize, - reloc_offset: usize, -} - -#[derive(Default, Clone, Copy)] -struct SymbolOffsets { - index: usize, - str_id: Option, - aux_count: u8, - storage_class: u8, -} - -impl<'a> Object<'a> { - pub(crate) fn xcoff_section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match section { - StandardSection::Text => (&[], &b".text"[..], SectionKind::Text, SectionFlags::None), - StandardSection::Data => (&[], &b".data"[..], SectionKind::Data, SectionFlags::None), - StandardSection::ReadOnlyData - | StandardSection::ReadOnlyDataWithRel - | StandardSection::ReadOnlyString => ( - &[], - &b".rdata"[..], - SectionKind::ReadOnlyData, - SectionFlags::None, - ), - StandardSection::UninitializedData => ( - &[], - &b".bss"[..], - SectionKind::UninitializedData, - SectionFlags::None, - ), - StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls, SectionFlags::None), - StandardSection::UninitializedTls => ( - &[], - &b".tbss"[..], - SectionKind::UninitializedTls, - SectionFlags::None, - ), - StandardSection::TlsVariables => { - // Unsupported section. - (&[], &[], SectionKind::TlsVariables, SectionFlags::None) - } - StandardSection::Common => { - // Unsupported section. - (&[], &[], SectionKind::Common, SectionFlags::None) - } - StandardSection::GnuProperty => { - // Unsupported section. - (&[], &[], SectionKind::Note, SectionFlags::None) - } - } - } - - pub(crate) fn xcoff_fixup_relocation(&mut self, relocation: &mut Relocation) -> i64 { - let constant = match relocation.kind { - RelocationKind::Relative => relocation.addend + 4, - _ => relocation.addend, - }; - relocation.addend -= constant; - constant - } - - pub(crate) fn xcoff_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - let is_64 = match self.architecture.address_size().unwrap() { - AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false, - AddressSize::U64 => true, - }; - - let (hdr_size, sechdr_size, rel_size, sym_size) = if is_64 { - ( - mem::size_of::(), - mem::size_of::(), - mem::size_of::(), - mem::size_of::(), - ) - } else { - ( - mem::size_of::(), - mem::size_of::(), - mem::size_of::(), - mem::size_of::(), - ) - }; - - // Calculate offsets and build strtab. - let mut offset = 0; - let mut strtab = StringTable::default(); - // We place the shared address 0 immediately after the section header table. - let mut address = 0; - - // XCOFF file header. - offset += hdr_size; - // Section headers. - offset += self.sections.len() * sechdr_size; - - // Calculate size of section data. - let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; - for (index, section) in self.sections.iter().enumerate() { - let len = section.data.len(); - let sectype = section.kind; - // Section address should be 0 for all sections except the .text, .data, and .bss sections. - if sectype == SectionKind::Data - || sectype == SectionKind::Text - || sectype == SectionKind::UninitializedData - { - section_offsets[index].address = address as u64; - address += len; - address = align(address, 4); - } else { - section_offsets[index].address = 0; - } - if len != 0 { - // Set the default section alignment as 4. - offset = align(offset, 4); - section_offsets[index].data_offset = offset; - offset += len; - } else { - section_offsets[index].data_offset = 0; - } - } - - // Calculate size of relocations. - for (index, section) in self.sections.iter().enumerate() { - let count = section.relocations.len(); - if count != 0 { - section_offsets[index].reloc_offset = offset; - offset += count * rel_size; - } else { - section_offsets[index].reloc_offset = 0; - } - } - - // Calculate size of symbols. - let mut file_str_id = None; - let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; - let mut symtab_count = 0; - for (index, symbol) in self.symbols.iter().enumerate() { - symbol_offsets[index].index = symtab_count; - symtab_count += 1; - - let storage_class = if let SymbolFlags::Xcoff { n_sclass, .. } = symbol.flags { - n_sclass - } else { - match symbol.kind { - SymbolKind::Null => xcoff::C_NULL, - SymbolKind::File => xcoff::C_FILE, - SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => { - if symbol.is_local() { - xcoff::C_STAT - } else if symbol.weak { - xcoff::C_WEAKEXT - } else { - xcoff::C_EXT - } - } - SymbolKind::Section | SymbolKind::Label | SymbolKind::Unknown => { - return Err(Error(format!( - "unimplemented symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - symbol.kind - ))); - } - } - }; - symbol_offsets[index].storage_class = storage_class; - - if storage_class == xcoff::C_FILE { - if is_64 && file_str_id.is_none() { - file_str_id = Some(strtab.add(b".file")); - } - if symbol.name.len() > 8 { - symbol_offsets[index].str_id = Some(strtab.add(&symbol.name)); - } - } else if is_64 || symbol.name.len() > 8 { - symbol_offsets[index].str_id = Some(strtab.add(&symbol.name)); - } - - symbol_offsets[index].aux_count = 0; - match storage_class { - xcoff::C_FILE => { - symbol_offsets[index].aux_count = 1; - symtab_count += 1; - } - xcoff::C_EXT | xcoff::C_WEAKEXT | xcoff::C_HIDEXT => { - symbol_offsets[index].aux_count = 1; - symtab_count += 1; - } - // TODO: support auxiliary entry for other types of symbol. - _ => {} - } - } - let symtab_offset = offset; - let symtab_len = symtab_count * sym_size; - offset += symtab_len; - - // Calculate size of strtab. - let strtab_offset = offset; - let mut strtab_data = Vec::new(); - // First 4 bytes of strtab are the length. - strtab.write(4, &mut strtab_data); - let strtab_len = strtab_data.len() + 4; - offset += strtab_len; - - // Start writing. - buffer - .reserve(offset) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - // Write file header. - if is_64 { - let header = xcoff::FileHeader64 { - f_magic: U16::new(BE, xcoff::MAGIC_64), - f_nscns: U16::new(BE, self.sections.len() as u16), - f_timdat: U32::new(BE, 0), - f_symptr: U64::new(BE, symtab_offset as u64), - f_nsyms: U32::new(BE, symtab_count as u32), - f_opthdr: U16::new(BE, 0), - f_flags: match self.flags { - FileFlags::Xcoff { f_flags } => U16::new(BE, f_flags), - _ => U16::default(), - }, - }; - buffer.write(&header); - } else { - let header = xcoff::FileHeader32 { - f_magic: U16::new(BE, xcoff::MAGIC_32), - f_nscns: U16::new(BE, self.sections.len() as u16), - f_timdat: U32::new(BE, 0), - f_symptr: U32::new(BE, symtab_offset as u32), - f_nsyms: U32::new(BE, symtab_count as u32), - f_opthdr: U16::new(BE, 0), - f_flags: match self.flags { - FileFlags::Xcoff { f_flags } => U16::new(BE, f_flags), - _ => U16::default(), - }, - }; - buffer.write(&header); - } - - // Write section headers. - for (index, section) in self.sections.iter().enumerate() { - let mut sectname = [0; 8]; - sectname - .get_mut(..section.name.len()) - .ok_or_else(|| { - Error(format!( - "section name `{}` is too long", - section.name().unwrap_or(""), - )) - })? - .copy_from_slice(§ion.name); - let flags = if let SectionFlags::Xcoff { s_flags } = section.flags { - s_flags - } else { - match section.kind { - SectionKind::Text - | SectionKind::ReadOnlyData - | SectionKind::ReadOnlyString - | SectionKind::ReadOnlyDataWithRel => xcoff::STYP_TEXT, - SectionKind::Data => xcoff::STYP_DATA, - SectionKind::UninitializedData => xcoff::STYP_BSS, - SectionKind::Tls => xcoff::STYP_TDATA, - SectionKind::UninitializedTls => xcoff::STYP_TBSS, - SectionKind::OtherString => xcoff::STYP_INFO, - SectionKind::Debug => xcoff::STYP_DEBUG, - SectionKind::Other | SectionKind::Metadata => 0, - SectionKind::Note - | SectionKind::Linker - | SectionKind::Common - | SectionKind::Unknown - | SectionKind::TlsVariables - | SectionKind::Elf(_) => { - return Err(Error(format!( - "unimplemented section `{}` kind {:?}", - section.name().unwrap_or(""), - section.kind - ))); - } - } - .into() - }; - if is_64 { - let section_header = xcoff::SectionHeader64 { - s_name: sectname, - s_paddr: U64::new(BE, section_offsets[index].address), - // This field has the same value as the s_paddr field. - s_vaddr: U64::new(BE, section_offsets[index].address), - s_size: U64::new(BE, section.data.len() as u64), - s_scnptr: U64::new(BE, section_offsets[index].data_offset as u64), - s_relptr: U64::new(BE, section_offsets[index].reloc_offset as u64), - s_lnnoptr: U64::new(BE, 0), - s_nreloc: U32::new(BE, section.relocations.len() as u32), - s_nlnno: U32::new(BE, 0), - s_flags: U32::new(BE, flags), - s_reserve: U32::new(BE, 0), - }; - buffer.write(§ion_header); - } else { - let section_header = xcoff::SectionHeader32 { - s_name: sectname, - s_paddr: U32::new(BE, section_offsets[index].address as u32), - // This field has the same value as the s_paddr field. - s_vaddr: U32::new(BE, section_offsets[index].address as u32), - s_size: U32::new(BE, section.data.len() as u32), - s_scnptr: U32::new(BE, section_offsets[index].data_offset as u32), - s_relptr: U32::new(BE, section_offsets[index].reloc_offset as u32), - s_lnnoptr: U32::new(BE, 0), - // TODO: If more than 65,534 relocation entries are required, the field - // value will be 65535, and an STYP_OVRFLO section header will contain - // the actual count of relocation entries in the s_paddr field. - s_nreloc: U16::new(BE, section.relocations.len() as u16), - s_nlnno: U16::new(BE, 0), - s_flags: U32::new(BE, flags), - }; - buffer.write(§ion_header); - } - } - - // Write section data. - for (index, section) in self.sections.iter().enumerate() { - let len = section.data.len(); - if len != 0 { - write_align(buffer, 4); - debug_assert_eq!(section_offsets[index].data_offset, buffer.len()); - buffer.write_bytes(§ion.data); - } - } - - // Write relocations. - for (index, section) in self.sections.iter().enumerate() { - if !section.relocations.is_empty() { - debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); - for reloc in §ion.relocations { - let rtype = match reloc.kind { - RelocationKind::Absolute => xcoff::R_POS, - RelocationKind::Relative => xcoff::R_REL, - RelocationKind::Got => xcoff::R_TOC, - RelocationKind::Xcoff(x) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }; - if is_64 { - let xcoff_rel = xcoff::Rel64 { - r_vaddr: U64::new(BE, reloc.offset), - r_symndx: U32::new(BE, symbol_offsets[reloc.symbol.0].index as u32), - // Specifies the bit length of the relocatable reference minus one. - r_rsize: (reloc.size - 1), - r_rtype: rtype, - }; - buffer.write(&xcoff_rel); - } else { - let xcoff_rel = xcoff::Rel32 { - r_vaddr: U32::new(BE, reloc.offset as u32), - r_symndx: U32::new(BE, symbol_offsets[reloc.symbol.0].index as u32), - r_rsize: (reloc.size - 1), - r_rtype: rtype, - }; - buffer.write(&xcoff_rel); - } - } - } - } - - // Write symbols. - debug_assert_eq!(symtab_offset, buffer.len()); - for (index, symbol) in self.symbols.iter().enumerate() { - let (n_value, section_kind) = if let SymbolSection::Section(id) = symbol.section { - ( - section_offsets[id.0].address + symbol.value, - self.sections[id.0].kind, - ) - } else { - (symbol.value, SectionKind::Unknown) - }; - let n_scnum = match symbol.section { - SymbolSection::None => { - debug_assert_eq!(symbol.kind, SymbolKind::File); - xcoff::N_DEBUG - } - SymbolSection::Undefined | SymbolSection::Common => xcoff::N_UNDEF, - SymbolSection::Absolute => xcoff::N_ABS, - SymbolSection::Section(id) => id.0 as i16 + 1, - }; - let n_sclass = symbol_offsets[index].storage_class; - let n_type = if (symbol.scope == SymbolScope::Linkage) - && (n_sclass == xcoff::C_EXT - || n_sclass == xcoff::C_WEAKEXT - || n_sclass == xcoff::C_HIDEXT) - { - xcoff::SYM_V_HIDDEN - } else { - 0 - }; - let n_numaux = symbol_offsets[index].aux_count; - if is_64 { - let str_id = if n_sclass == xcoff::C_FILE { - file_str_id.unwrap() - } else { - symbol_offsets[index].str_id.unwrap() - }; - let xcoff_sym = xcoff::Symbol64 { - n_value: U64::new(BE, n_value), - n_offset: U32::new(BE, strtab.get_offset(str_id) as u32), - n_scnum: I16::new(BE, n_scnum), - n_type: U16::new(BE, n_type), - n_sclass, - n_numaux, - }; - buffer.write(&xcoff_sym); - } else { - let mut sym_name = [0; 8]; - if n_sclass == xcoff::C_FILE { - sym_name[..5].copy_from_slice(b".file"); - } else if symbol.name.len() <= 8 { - sym_name[..symbol.name.len()].copy_from_slice(&symbol.name[..]); - } else { - let str_offset = strtab.get_offset(symbol_offsets[index].str_id.unwrap()); - sym_name[4..8].copy_from_slice(&u32::to_be_bytes(str_offset as u32)); - } - let xcoff_sym = xcoff::Symbol32 { - n_name: sym_name, - n_value: U32::new(BE, n_value as u32), - n_scnum: I16::new(BE, n_scnum), - n_type: U16::new(BE, n_type), - n_sclass, - n_numaux, - }; - buffer.write(&xcoff_sym); - } - // Generate auxiliary entries. - if n_sclass == xcoff::C_FILE { - debug_assert_eq!(n_numaux, 1); - let mut x_fname = [0; 8]; - if symbol.name.len() <= 8 { - x_fname[..symbol.name.len()].copy_from_slice(&symbol.name[..]); - } else { - let str_offset = strtab.get_offset(symbol_offsets[index].str_id.unwrap()); - x_fname[4..8].copy_from_slice(&u32::to_be_bytes(str_offset as u32)); - } - if is_64 { - let file_aux = xcoff::FileAux64 { - x_fname, - x_fpad: Default::default(), - x_ftype: xcoff::XFT_FN, - x_freserve: Default::default(), - x_auxtype: xcoff::AUX_FILE, - }; - buffer.write(&file_aux); - } else { - let file_aux = xcoff::FileAux32 { - x_fname, - x_fpad: Default::default(), - x_ftype: xcoff::XFT_FN, - x_freserve: Default::default(), - }; - buffer.write(&file_aux); - } - } else if n_sclass == xcoff::C_EXT - || n_sclass == xcoff::C_WEAKEXT - || n_sclass == xcoff::C_HIDEXT - { - debug_assert_eq!(n_numaux, 1); - let (x_smtyp, x_smclas) = if let SymbolFlags::Xcoff { - x_smtyp, x_smclas, .. - } = symbol.flags - { - (x_smtyp, x_smclas) - } else { - match symbol.kind { - SymbolKind::Text => (xcoff::XTY_SD, xcoff::XMC_PR), - SymbolKind::Data => { - if section_kind == SectionKind::UninitializedData { - (xcoff::XTY_CM, xcoff::XMC_BS) - } else if section_kind == SectionKind::ReadOnlyData { - (xcoff::XTY_SD, xcoff::XMC_RO) - } else { - (xcoff::XTY_SD, xcoff::XMC_RW) - } - } - SymbolKind::Tls => { - if section_kind == SectionKind::UninitializedTls { - (xcoff::XTY_CM, xcoff::XMC_UL) - } else { - (xcoff::XTY_SD, xcoff::XMC_TL) - } - } - _ => { - return Err(Error(format!( - "unimplemented symbol `{}` kind {:?}", - symbol.name().unwrap_or(""), - symbol.kind - ))); - } - } - }; - let scnlen = if let SymbolFlags::Xcoff { - containing_csect: Some(containing_csect), - .. - } = symbol.flags - { - symbol_offsets[containing_csect.0].index as u64 - } else { - symbol.size - }; - if is_64 { - let csect_aux = xcoff::CsectAux64 { - x_scnlen_lo: U32::new(BE, (scnlen & 0xFFFFFFFF) as u32), - x_scnlen_hi: U32::new(BE, ((scnlen >> 32) & 0xFFFFFFFF) as u32), - x_parmhash: U32::new(BE, 0), - x_snhash: U16::new(BE, 0), - x_smtyp, - x_smclas, - pad: 0, - x_auxtype: xcoff::AUX_CSECT, - }; - buffer.write(&csect_aux); - } else { - let csect_aux = xcoff::CsectAux32 { - x_scnlen: U32::new(BE, scnlen as u32), - x_parmhash: U32::new(BE, 0), - x_snhash: U16::new(BE, 0), - x_smtyp, - x_smclas, - x_stab: U32::new(BE, 0), - x_snstab: U16::new(BE, 0), - }; - buffer.write(&csect_aux); - } - } - } - - // Write string table. - debug_assert_eq!(strtab_offset, buffer.len()); - buffer.write_bytes(&u32::to_be_bytes(strtab_len as u32)); - buffer.write_bytes(&strtab_data); - - debug_assert_eq!(offset, buffer.len()); - Ok(()) - } -} diff --git a/vendor/object/src/xcoff.rs b/vendor/object/src/xcoff.rs deleted file mode 100644 index dbe5d73..0000000 --- a/vendor/object/src/xcoff.rs +++ /dev/null @@ -1,905 +0,0 @@ -//! XCOFF definitions -//! -//! These definitions are independent of read/write support, although we do implement -//! some traits useful for those. -//! -//! This module is the equivalent of /usr/include/xcoff.h, and is based heavily on it. - -#![allow(missing_docs)] - -use crate::endian::{BigEndian as BE, I16, U16, U32, U64}; -use crate::pod::Pod; - -/// The header at the start of every 32-bit XCOFF file. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileHeader32 { - /// Magic number. Must be 0x01DF. - pub f_magic: U16, - /// Number of sections. - pub f_nscns: U16, - /// Time and date of file creation. - pub f_timdat: U32, - /// Byte offset to symbol table start. - pub f_symptr: U32, - /// Number of entries in symbol table. - pub f_nsyms: U32, - /// Number of bytes in optional header - pub f_opthdr: U16, - /// Extra flags. - pub f_flags: U16, -} - -/// The header at the start of every 64-bit XCOFF file. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileHeader64 { - /// Magic number. Must be 0x01F7. - pub f_magic: U16, - /// Number of sections. - pub f_nscns: U16, - /// Time and date of file creation - pub f_timdat: U32, - /// Byte offset to symbol table start. - pub f_symptr: U64, - /// Number of bytes in optional header - pub f_opthdr: U16, - /// Extra flags. - pub f_flags: U16, - /// Number of entries in symbol table. - pub f_nsyms: U32, -} - -// Values for `f_magic`. -// -/// the 64-bit mach magic number -pub const MAGIC_64: u16 = 0x01F7; -/// the 32-bit mach magic number -pub const MAGIC_32: u16 = 0x01DF; - -// Values for `f_flags`. -// -/// Indicates that the relocation information for binding has been removed from -/// the file. -pub const F_RELFLG: u16 = 0x0001; -/// Indicates that the file is executable. No unresolved external references exist. -pub const F_EXEC: u16 = 0x0002; -/// Indicates that line numbers have been stripped from the file by a utility program. -pub const F_LNNO: u16 = 0x0004; -/// Indicates that the file was profiled with the fdpr command. -pub const F_FDPR_PROF: u16 = 0x0010; -/// Indicates that the file was reordered with the fdpr command. -pub const F_FDPR_OPTI: u16 = 0x0020; -/// Indicates that the file uses Very Large Program Support. -pub const F_DSA: u16 = 0x0040; -/// Indicates that one of the members of the auxiliary header specifying the -/// medium page sizes is non-zero. -pub const F_VARPG: u16 = 0x0100; -/// Indicates the file is dynamically loadable and executable. External references -/// are resolved by way of imports, and the file might contain exports and loader -/// relocation. -pub const F_DYNLOAD: u16 = 0x1000; -/// Indicates the file is a shared object (shared library). The file is separately -/// loadable. That is, it is not normally bound with other objects, and its loader -/// exports symbols are used as automatic import symbols for other object files. -pub const F_SHROBJ: u16 = 0x2000; -/// If the object file is a member of an archive, it can be loaded by the system -/// loader, but the member is ignored by the binder. If the object file is not in -/// an archive, this flag has no effect. -pub const F_LOADONLY: u16 = 0x4000; - -/// The auxiliary header immediately following file header. If the value of the -/// f_opthdr field in the file header is 0, the auxiliary header does not exist. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AuxHeader32 { - /// Flags. - pub o_mflag: U16, - /// Version. - pub o_vstamp: U16, - /// Text size in bytes. - pub o_tsize: U32, - /// Initialized data size in bytes. - pub o_dsize: U32, - /// Uninitialized data size in bytes. - pub o_bsize: U32, - /// Entry point descriptor (virtual address). - pub o_entry: U32, - /// Base address of text (virtual address). - pub o_text_start: U32, - /// Base address of data (virtual address). - pub o_data_start: U32, - /// Address of TOC anchor. - pub o_toc: U32, - /// Section number for entry point. - pub o_snentry: U16, - /// Section number for .text. - pub o_sntext: U16, - /// Section number for .data. - pub o_sndata: U16, - /// Section number for TOC. - pub o_sntoc: U16, - /// Section number for loader data. - pub o_snloader: U16, - /// Section number for .bss. - pub o_snbss: U16, - /// Maximum alignment for .text. - pub o_algntext: U16, - /// Maximum alignment for .data. - pub o_algndata: U16, - /// Module type field. - pub o_modtype: U16, - /// Bit flags - cpu types of objects. - pub o_cpuflag: u8, - /// Reserved for CPU type. - pub o_cputype: u8, - /// Maximum stack size allowed (bytes). - pub o_maxstack: U32, - /// Maximum data size allowed (bytes). - pub o_maxdata: U32, - /// Reserved for debuggers. - pub o_debugger: U32, - /// Requested text page size. - pub o_textpsize: u8, - /// Requested data page size. - pub o_datapsize: u8, - /// Requested stack page size. - pub o_stackpsize: u8, - /// Flags and thread-local storage alignment. - pub o_flags: u8, - /// Section number for .tdata. - pub o_sntdata: U16, - /// Section number for .tbss. - pub o_sntbss: U16, -} - -/// The auxiliary header immediately following file header. If the value of the -/// f_opthdr field in the file header is 0, the auxiliary header does not exist. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct AuxHeader64 { - /// Flags. - pub o_mflag: U16, - /// Version. - pub o_vstamp: U16, - /// Reserved for debuggers. - pub o_debugger: U32, - /// Base address of text (virtual address). - pub o_text_start: U64, - /// Base address of data (virtual address). - pub o_data_start: U64, - /// Address of TOC anchor. - pub o_toc: U64, - /// Section number for entry point. - pub o_snentry: U16, - /// Section number for .text. - pub o_sntext: U16, - /// Section number for .data. - pub o_sndata: U16, - /// Section number for TOC. - pub o_sntoc: U16, - /// Section number for loader data. - pub o_snloader: U16, - /// Section number for .bss. - pub o_snbss: U16, - /// Maximum alignment for .text. - pub o_algntext: U16, - /// Maximum alignment for .data. - pub o_algndata: U16, - /// Module type field. - pub o_modtype: U16, - /// Bit flags - cpu types of objects. - pub o_cpuflag: u8, - /// Reserved for CPU type. - pub o_cputype: u8, - /// Requested text page size. - pub o_textpsize: u8, - /// Requested data page size. - pub o_datapsize: u8, - /// Requested stack page size. - pub o_stackpsize: u8, - /// Flags and thread-local storage alignment. - pub o_flags: u8, - /// Text size in bytes. - pub o_tsize: U64, - /// Initialized data size in bytes. - pub o_dsize: U64, - /// Uninitialized data size in bytes. - pub o_bsize: U64, - /// Entry point descriptor (virtual address). - pub o_entry: U64, - /// Maximum stack size allowed (bytes). - pub o_maxstack: U64, - /// Maximum data size allowed (bytes). - pub o_maxdata: U64, - /// Section number for .tdata. - pub o_sntdata: U16, - /// Section number for .tbss. - pub o_sntbss: U16, - /// XCOFF64 flags. - pub o_x64flags: U16, - /// Reserved. - pub o_resv3a: U16, - /// Reserved. - pub o_resv3: [U32; 2], -} - -/// Some AIX programs generate auxiliary headers for 32-bit object files that -/// end after the data_start field. -pub const AOUTHSZ_SHORT: u16 = 28; - -/// Section header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SectionHeader32 { - /// Section name. - pub s_name: [u8; 8], - /// Physical address. - pub s_paddr: U32, - /// Virtual address (same as physical address). - pub s_vaddr: U32, - /// Section size. - pub s_size: U32, - /// Offset in file to raw data for section. - pub s_scnptr: U32, - /// Offset in file to relocation entries for section. - pub s_relptr: U32, - /// Offset in file to line number entries for section. - pub s_lnnoptr: U32, - /// Number of relocation entries. - pub s_nreloc: U16, - /// Number of line number entries. - pub s_nlnno: U16, - /// Flags to define the section type. - pub s_flags: U32, -} - -/// Section header. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SectionHeader64 { - /// Section name. - pub s_name: [u8; 8], - /// Physical address. - pub s_paddr: U64, - /// Virtual address (same as physical address). - pub s_vaddr: U64, - /// Section size. - pub s_size: U64, - /// Offset in file to raw data for section. - pub s_scnptr: U64, - /// Offset in file to relocation entries for section. - pub s_relptr: U64, - /// Offset in file to line number entries for section. - pub s_lnnoptr: U64, - /// Number of relocation entries. - pub s_nreloc: U32, - /// Number of line number entries. - pub s_nlnno: U32, - /// Flags to define the section type. - pub s_flags: U32, - /// Reserved. - pub s_reserve: U32, -} - -// Values for `s_flags`. -// -/// "regular" section -pub const STYP_REG: u16 = 0x00; -/// Specifies a pad section. A section of this type is used to provide alignment -/// padding between sections within an XCOFF executable object file. This section -/// header type is obsolete since padding is allowed in an XCOFF file without a -/// corresponding pad section header. -pub const STYP_PAD: u16 = 0x08; -/// Specifies a DWARF debugging section, which provide source file and symbol -/// information for the symbolic debugger. -pub const STYP_DWARF: u16 = 0x10; -/// Specifies an executable text (code) section. A section of this type contains -/// the executable instructions of a program. -pub const STYP_TEXT: u16 = 0x20; -/// Specifies an initialized data section. A section of this type contains the -/// initialized data and the TOC of a program. -pub const STYP_DATA: u16 = 0x40; -/// Specifies an uninitialized data section. A section header of this type -/// defines the uninitialized data of a program. -pub const STYP_BSS: u16 = 0x80; -/// Specifies an exception section. A section of this type provides information -/// to identify the reason that a trap or exception occurred within an executable -/// object program. -pub const STYP_EXCEPT: u16 = 0x0100; -/// Specifies a comment section. A section of this type provides comments or data -/// to special processing utility programs. -pub const STYP_INFO: u16 = 0x0200; -/// Specifies an initialized thread-local data section. -pub const STYP_TDATA: u16 = 0x0400; -/// Specifies an uninitialized thread-local data section. -pub const STYP_TBSS: u16 = 0x0800; -/// Specifies a loader section. A section of this type contains object file -/// information for the system loader to load an XCOFF executable. The information -/// includes imported symbols, exported symbols, relocation data, type-check -/// information, and shared object names. -pub const STYP_LOADER: u16 = 0x1000; -/// Specifies a debug section. A section of this type contains stabstring -/// information used by the symbolic debugger. -pub const STYP_DEBUG: u16 = 0x2000; -/// Specifies a type-check section. A section of this type contains -/// parameter/argument type-check strings used by the binder. -pub const STYP_TYPCHK: u16 = 0x4000; -/// Specifies a relocation or line-number field overflow section. A section -/// header of this type contains the count of relocation entries and line -/// number entries for some other section. This section header is required -/// when either of the counts exceeds 65,534. -pub const STYP_OVRFLO: u16 = 0x8000; - -pub const SSUBTYP_DWINFO: u32 = 0x10000; -pub const SSUBTYP_DWLINE: u32 = 0x20000; -pub const SSUBTYP_DWPBNMS: u32 = 0x30000; -pub const SSUBTYP_DWPBTYP: u32 = 0x40000; -pub const SSUBTYP_DWARNGE: u32 = 0x50000; -pub const SSUBTYP_DWABREV: u32 = 0x60000; -pub const SSUBTYP_DWSTR: u32 = 0x70000; -pub const SSUBTYP_DWRNGES: u32 = 0x80000; -pub const SSUBTYP_DWLOC: u32 = 0x90000; -pub const SSUBTYP_DWFRAME: u32 = 0xA0000; -pub const SSUBTYP_DWMAC: u32 = 0xB0000; - -pub const SIZEOF_SYMBOL: usize = 18; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct SymbolBytes(pub [u8; SIZEOF_SYMBOL]); - -/// Symbol table entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Symbol32 { - /// Symbol name. - /// - /// If first 4 bytes are 0, then second 4 bytes are offset into string table. - pub n_name: [u8; 8], - /// Symbol value; storage class-dependent. - pub n_value: U32, - /// Section number of symbol. - pub n_scnum: I16, - /// Basic and derived type specification. - pub n_type: U16, - /// Storage class of symbol. - pub n_sclass: u8, - /// Number of auxiliary entries. - pub n_numaux: u8, -} - -/// Symbol table entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Symbol64 { - /// Symbol value; storage class-dependent. - pub n_value: U64, - /// Offset of the name in string table or .debug section. - pub n_offset: U32, - /// Section number of symbol. - pub n_scnum: I16, - /// Basic and derived type specification. - pub n_type: U16, - /// Storage class of symbol. - pub n_sclass: u8, - /// Number of auxiliary entries. - pub n_numaux: u8, -} - -// Values for `n_scnum`. -// -/// A special symbolic debugging symbol. -pub const N_DEBUG: i16 = -2; -/// An absolute symbol. The symbol has a value but is not relocatable. -pub const N_ABS: i16 = -1; -/// An undefined external symbol. -pub const N_UNDEF: i16 = 0; - -// Vlaues for `n_type`. -// -/// Values for visibility as they would appear when encoded in the high 4 bits -/// of the 16-bit unsigned n_type field of symbol table entries. Valid for -/// 32-bit XCOFF only when the o_vstamp in the auxiliary header is greater than 1. -pub const SYM_V_MASK: u16 = 0xF000; -pub const SYM_V_INTERNAL: u16 = 0x1000; -pub const SYM_V_HIDDEN: u16 = 0x2000; -pub const SYM_V_PROTECTED: u16 = 0x3000; -pub const SYM_V_EXPORTED: u16 = 0x4000; - -// Values for `n_sclass`. -// -// Storage classes used for symbolic debugging symbols. -// -/// Source file name and compiler information. -pub const C_FILE: u8 = 103; -/// Beginning of include file. -pub const C_BINCL: u8 = 108; -/// Ending of include file. -pub const C_EINCL: u8 = 109; -/// Global variable. -pub const C_GSYM: u8 = 128; -/// Statically allocated symbol. -pub const C_STSYM: u8 = 133; -/// Beginning of common block. -pub const C_BCOMM: u8 = 135; -/// End of common block. -pub const C_ECOMM: u8 = 137; -/// Alternate entry. -pub const C_ENTRY: u8 = 141; -/// Beginning of static block. -pub const C_BSTAT: u8 = 143; -/// End of static block. -pub const C_ESTAT: u8 = 144; -/// Global thread-local variable. -pub const C_GTLS: u8 = 145; -/// Static thread-local variable. -pub const C_STTLS: u8 = 146; -/// DWARF section symbol. -pub const C_DWARF: u8 = 112; -// -// Storage classes used for absolute symbols. -// -/// Automatic variable allocated on stack. -pub const C_LSYM: u8 = 129; -/// Argument to subroutine allocated on stack. -pub const C_PSYM: u8 = 130; -/// Register variable. -pub const C_RSYM: u8 = 131; -/// Argument to function or procedure stored in register. -pub const C_RPSYM: u8 = 132; -/// Local member of common block. -pub const C_ECOML: u8 = 136; -/// Function or procedure. -pub const C_FUN: u8 = 142; -// -// Storage classes used for undefined external symbols or symbols of general sections. -// -/// External symbol. -pub const C_EXT: u8 = 2; -/// Weak external symbol. -pub const C_WEAKEXT: u8 = 111; -// -// Storage classes used for symbols of general sections. -// -/// Symbol table entry marked for deletion. -pub const C_NULL: u8 = 0; -/// Static. -pub const C_STAT: u8 = 3; -/// Beginning or end of inner block. -pub const C_BLOCK: u8 = 100; -/// Beginning or end of function. -pub const C_FCN: u8 = 101; -/// Un-named external symbol. -pub const C_HIDEXT: u8 = 107; -/// Comment string in .info section. -pub const C_INFO: u8 = 110; -/// Declaration of object (type). -pub const C_DECL: u8 = 140; -// -// Storage classes - Obsolete/Undocumented. -// -/// Automatic variable. -pub const C_AUTO: u8 = 1; -/// Register variable. -pub const C_REG: u8 = 4; -/// External definition. -pub const C_EXTDEF: u8 = 5; -/// Label. -pub const C_LABEL: u8 = 6; -/// Undefined label. -pub const C_ULABEL: u8 = 7; -/// Member of structure. -pub const C_MOS: u8 = 8; -/// Function argument. -pub const C_ARG: u8 = 9; -/// Structure tag. -pub const C_STRTAG: u8 = 10; -/// Member of union. -pub const C_MOU: u8 = 11; -/// Union tag. -pub const C_UNTAG: u8 = 12; -/// Type definition. -pub const C_TPDEF: u8 = 13; -/// Undefined static. -pub const C_USTATIC: u8 = 14; -/// Enumeration tag. -pub const C_ENTAG: u8 = 15; -/// Member of enumeration. -pub const C_MOE: u8 = 16; -/// Register parameter. -pub const C_REGPARM: u8 = 17; -/// Bit field. -pub const C_FIELD: u8 = 18; -/// End of structure. -pub const C_EOS: u8 = 102; -/// Duplicate tag. -pub const C_ALIAS: u8 = 105; -/// Special storage class for external. -pub const C_HIDDEN: u8 = 106; -/// Physical end of function. -pub const C_EFCN: u8 = 255; -/// Reserved. -pub const C_TCSYM: u8 = 134; - -/// File Auxiliary Entry for C_FILE Symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileAux32 { - /// The source file name or compiler-related string. - /// - /// If first 4 bytes are 0, then second 4 bytes are offset into string table. - pub x_fname: [u8; 8], - /// Pad size for file name. - pub x_fpad: [u8; 6], - /// The source-file string type. - pub x_ftype: u8, - /// Reserved. - pub x_freserve: [u8; 3], -} - -/// File Auxiliary Entry for C_FILE Symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FileAux64 { - /// The source file name or compiler-related string. - /// - /// If first 4 bytes are 0, then second 4 bytes are offset into string table. - pub x_fname: [u8; 8], - /// Pad size for file name. - pub x_fpad: [u8; 6], - /// The source-file string type. - pub x_ftype: u8, - /// Reserved. - pub x_freserve: [u8; 2], - /// Specifies the type of auxiliary entry. Contains _AUX_FILE for this auxiliary entry. - pub x_auxtype: u8, -} - -// Values for `x_ftype`. -// -/// Specifies the source-file name. -pub const XFT_FN: u8 = 0; -/// Specifies the compiler time stamp. -pub const XFT_CT: u8 = 1; -/// Specifies the compiler version number. -pub const XFT_CV: u8 = 2; -/// Specifies compiler-defined information. -pub const XFT_CD: u8 = 128; - -/// Csect auxiliary entry for C_EXT, C_WEAKEXT, and C_HIDEXT symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct CsectAux32 { - /// Section length. - pub x_scnlen: U32, - /// Offset of parameter type-check hash in .typchk section. - pub x_parmhash: U32, - /// .typchk section number. - pub x_snhash: U16, - /// Symbol alignment and type. - pub x_smtyp: u8, - /// Storage mapping class. - pub x_smclas: u8, - /// Reserved. - pub x_stab: U32, - /// x_snstab. - pub x_snstab: U16, -} - -/// Csect auxiliary entry for C_EXT, C_WEAKEXT, and C_HIDEXT symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct CsectAux64 { - /// Low 4 bytes of section length. - pub x_scnlen_lo: U32, - /// Offset of parameter type-check hash in .typchk section. - pub x_parmhash: U32, - /// .typchk section number. - pub x_snhash: U16, - /// Symbol alignment and type. - pub x_smtyp: u8, - /// Storage mapping class. - pub x_smclas: u8, - /// High 4 bytes of section length. - pub x_scnlen_hi: U32, - /// Reserved. - pub pad: u8, - /// Contains _AUX_CSECT; indicates type of auxiliary entry. - pub x_auxtype: u8, -} - -// Values for `x_smtyp`. -// -/// External reference. -pub const XTY_ER: u8 = 0; -/// Csect definition for initialized storage. -pub const XTY_SD: u8 = 1; -/// Defines an entry point to an initialized csect. -pub const XTY_LD: u8 = 2; -/// Common csect definition. For uninitialized storage. -pub const XTY_CM: u8 = 3; - -// Values for `x_smclas`. -// -// READ ONLY CLASSES -// -/// Program Code -pub const XMC_PR: u8 = 0; -/// Read Only Constant -pub const XMC_RO: u8 = 1; -/// Debug Dictionary Table -pub const XMC_DB: u8 = 2; -/// Global Linkage (Interfile Interface Code) -pub const XMC_GL: u8 = 6; -/// Extended Operation (Pseudo Machine Instruction) -pub const XMC_XO: u8 = 7; -/// Supervisor Call (32-bit process only) -pub const XMC_SV: u8 = 8; -/// Supervisor Call for 64-bit process -pub const XMC_SV64: u8 = 17; -/// Supervisor Call for both 32- and 64-bit processes -pub const XMC_SV3264: u8 = 18; -/// Traceback Index csect -pub const XMC_TI: u8 = 12; -/// Traceback Table csect -pub const XMC_TB: u8 = 13; -// -// READ WRITE CLASSES -// -/// Read Write Data -pub const XMC_RW: u8 = 5; -/// TOC Anchor for TOC Addressability -pub const XMC_TC0: u8 = 15; -/// General TOC item -pub const XMC_TC: u8 = 3; -/// Scalar data item in the TOC -pub const XMC_TD: u8 = 16; -/// Descriptor csect -pub const XMC_DS: u8 = 10; -/// Unclassified - Treated as Read Write -pub const XMC_UA: u8 = 4; -/// BSS class (uninitialized static internal) -pub const XMC_BS: u8 = 9; -/// Un-named Fortran Common -pub const XMC_UC: u8 = 11; -/// Initialized thread-local variable -pub const XMC_TL: u8 = 20; -/// Uninitialized thread-local variable -pub const XMC_UL: u8 = 21; -/// Symbol mapped at the end of TOC -pub const XMC_TE: u8 = 22; - -/// Function auxiliary entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FunAux32 { - /// File offset to exception table entry. - pub x_exptr: U32, - /// Size of function in bytes. - pub x_fsize: U32, - /// File pointer to line number - pub x_lnnoptr: U32, - /// Symbol table index of next entry beyond this function. - pub x_endndx: U32, - /// Pad - pub pad: U16, -} - -/// Function auxiliary entry. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct FunAux64 { - /// File pointer to line number - pub x_lnnoptr: U64, - /// Size of function in bytes. - pub x_fsize: U32, - /// Symbol table index of next entry beyond this function. - pub x_endndx: U32, - /// Pad - pub pad: u8, - /// Contains _AUX_FCN; Type of auxiliary entry. - pub x_auxtype: u8, -} - -/// Exception auxiliary entry. (XCOFF64 only) -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct ExpAux { - /// File offset to exception table entry. - pub x_exptr: U64, - /// Size of function in bytes. - pub x_fsize: U32, - /// Symbol table index of next entry beyond this function. - pub x_endndx: U32, - /// Pad - pub pad: u8, - /// Contains _AUX_EXCEPT; Type of auxiliary entry - pub x_auxtype: u8, -} - -/// Block auxiliary entry for the C_BLOCK and C_FCN Symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct BlockAux32 { - /// Reserved. - pub pad: [u8; 2], - /// High-order 2 bytes of the source line number. - pub x_lnnohi: U16, - /// Low-order 2 bytes of the source line number. - pub x_lnnolo: U16, - /// Reserved. - pub pad2: [u8; 12], -} - -/// Block auxiliary entry for the C_BLOCK and C_FCN Symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct BlockAux64 { - /// Source line number. - pub x_lnno: U32, - /// Reserved. - pub pad: [u8; 13], - /// Contains _AUX_SYM; Type of auxiliary entry. - pub x_auxtype: u8, -} - -/// Section auxiliary entry for the C_STAT Symbol. (XCOFF32 Only) -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct StatAux { - /// Section length. - pub x_scnlen: U32, - /// Number of relocation entries. - pub x_nreloc: U16, - /// Number of line numbers. - pub x_nlinno: U16, - /// Reserved. - pub pad: [u8; 10], -} - -/// Section auxiliary entry Format for C_DWARF symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DwarfAux32 { - /// Length of portion of section represented by symbol. - pub x_scnlen: U32, - /// Reserved. - pub pad: [u8; 4], - /// Number of relocation entries in section. - pub x_nreloc: U32, - /// Reserved. - pub pad2: [u8; 6], -} - -/// Section auxiliary entry Format for C_DWARF symbols. -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct DwarfAux64 { - /// Length of portion of section represented by symbol. - pub x_scnlen: U64, - /// Number of relocation entries in section. - pub x_nreloc: U64, - /// Reserved. - pub pad: u8, - /// Contains _AUX_SECT; Type of Auxiliary entry. - pub x_auxtype: u8, -} - -// Values for `x_auxtype` -// -/// Identifies an exception auxiliary entry. -pub const AUX_EXCEPT: u8 = 255; -/// Identifies a function auxiliary entry. -pub const AUX_FCN: u8 = 254; -/// Identifies a symbol auxiliary entry. -pub const AUX_SYM: u8 = 253; -/// Identifies a file auxiliary entry. -pub const AUX_FILE: u8 = 252; -/// Identifies a csect auxiliary entry. -pub const AUX_CSECT: u8 = 251; -/// Identifies a SECT auxiliary entry. -pub const AUX_SECT: u8 = 250; - -/// Relocation table entry -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rel32 { - /// Virtual address (position) in section to be relocated. - pub r_vaddr: U32, - /// Symbol table index of item that is referenced. - pub r_symndx: U32, - /// Relocation size and information. - pub r_rsize: u8, - /// Relocation type. - pub r_rtype: u8, -} - -/// Relocation table entry -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Rel64 { - /// Virtual address (position) in section to be relocated. - pub r_vaddr: U64, - /// Symbol table index of item that is referenced. - pub r_symndx: U32, - /// Relocation size and information. - pub r_rsize: u8, - /// Relocation type. - pub r_rtype: u8, -} - -// Values for `r_rtype`. -// -/// Positive relocation. -pub const R_POS: u8 = 0x00; -/// Positive indirect load relocation. -pub const R_RL: u8 = 0x0c; -/// Positive load address relocation. Modifiable instruction. -pub const R_RLA: u8 = 0x0d; -/// Negative relocation. -pub const R_NEG: u8 = 0x01; -/// Relative to self relocation. -pub const R_REL: u8 = 0x02; -/// Relative to the TOC relocation. -pub const R_TOC: u8 = 0x03; -/// TOC relative indirect load relocation. -pub const R_TRL: u8 = 0x12; -/// Relative to the TOC or to the thread-local storage base relocation. -pub const R_TRLA: u8 = 0x13; -/// Global linkage-external TOC address relocation. -pub const R_GL: u8 = 0x05; -/// Local object TOC address relocation. -pub const R_TCL: u8 = 0x06; -/// A non-relocating relocation. -pub const R_REF: u8 = 0x0f; -/// Branch absolute relocation. References a non-modifiable instruction. -pub const R_BA: u8 = 0x08; -/// Branch relative to self relocation. References a non-modifiable instruction. -pub const R_BR: u8 = 0x0a; -/// Branch absolute relocation. References a modifiable instruction. -pub const R_RBA: u8 = 0x18; -/// Branch relative to self relocation. References a modifiable instruction. -pub const R_RBR: u8 = 0x1a; -/// General-dynamic reference to TLS symbol. -pub const R_TLS: u8 = 0x20; -/// Initial-exec reference to TLS symbol. -pub const R_TLS_IE: u8 = 0x21; -/// Local-dynamic reference to TLS symbol. -pub const R_TLS_LD: u8 = 0x22; -/// Local-exec reference to TLS symbol. -pub const R_TLS_LE: u8 = 0x23; -/// Module reference to TLS. -pub const R_TLSM: u8 = 0x24; -/// Module reference to the local TLS storage. -pub const R_TLSML: u8 = 0x25; -/// Relative to TOC upper. -pub const R_TOCU: u8 = 0x30; -/// Relative to TOC lower. -pub const R_TOCL: u8 = 0x31; - -unsafe_impl_pod!( - FileHeader32, - FileHeader64, - AuxHeader32, - AuxHeader64, - SectionHeader32, - SectionHeader64, - SymbolBytes, - Symbol32, - Symbol64, - FileAux32, - FileAux64, - CsectAux32, - CsectAux64, - FunAux32, - FunAux64, - ExpAux, - BlockAux32, - BlockAux64, - StatAux, - DwarfAux32, - DwarfAux64, - Rel32, - Rel64, -); diff --git a/vendor/object/tests/integration.rs b/vendor/object/tests/integration.rs deleted file mode 100644 index 6ebcb54..0000000 --- a/vendor/object/tests/integration.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod read; -mod round_trip; diff --git a/vendor/object/tests/parse_self.rs b/vendor/object/tests/parse_self.rs deleted file mode 100644 index 1e7df67..0000000 --- a/vendor/object/tests/parse_self.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![cfg(feature = "read")] -use object::{File, Object}; -use std::{env, fs}; - -#[test] -fn parse_self() { - let exe = env::current_exe().unwrap(); - let data = fs::read(exe).unwrap(); - let object = File::parse(&*data).unwrap(); - assert!(object.entry() != 0); - assert!(object.sections().count() != 0); -} - -#[cfg(feature = "std")] -#[test] -fn parse_self_cache() { - use object::read::{ReadCache, ReadRef}; - let exe = env::current_exe().unwrap(); - let file = fs::File::open(exe).unwrap(); - let cache = ReadCache::new(file); - let data = cache.range(0, cache.len().unwrap()); - let object = File::parse(data).unwrap(); - assert!(object.entry() != 0); - assert!(object.sections().count() != 0); -} diff --git a/vendor/object/tests/read/coff.rs b/vendor/object/tests/read/coff.rs deleted file mode 100644 index dcf3b3c..0000000 --- a/vendor/object/tests/read/coff.rs +++ /dev/null @@ -1,23 +0,0 @@ -use object::{pe, read, Object, ObjectSection}; -use std::fs; -use std::path::PathBuf; - -#[cfg(feature = "coff")] -#[test] -fn coff_extended_relocations() { - let path_to_obj: PathBuf = ["testfiles", "coff", "relocs_overflow.o"].iter().collect(); - let contents = fs::read(&path_to_obj).expect("Could not read relocs_overflow.o"); - let file = - read::coff::CoffFile::<_>::parse(&contents[..]).expect("Could not parse relocs_overflow.o"); - let code_section = file - .section_by_name(".text") - .expect("Could not find .text section in relocs_overflow.o"); - match code_section.flags() { - object::SectionFlags::Coff { characteristics } => { - assert!(characteristics & pe::IMAGE_SCN_LNK_NRELOC_OVFL != 0) - } - _ => panic!("Invalid section flags flavour."), - }; - let relocations = code_section.relocations().collect::>(); - assert_eq!(relocations.len(), 65536); -} diff --git a/vendor/object/tests/read/mod.rs b/vendor/object/tests/read/mod.rs deleted file mode 100644 index d60d193..0000000 --- a/vendor/object/tests/read/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![cfg(feature = "read")] - -mod coff; diff --git a/vendor/object/tests/round_trip/bss.rs b/vendor/object/tests/round_trip/bss.rs deleted file mode 100644 index 1354fcc..0000000 --- a/vendor/object/tests/round_trip/bss.rs +++ /dev/null @@ -1,255 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::read::{Object, ObjectSection, ObjectSymbol}; -use object::{read, write}; -use object::{ - Architecture, BinaryFormat, Endianness, SectionKind, SymbolFlags, SymbolKind, SymbolScope, -}; - -#[test] -fn coff_x86_64_bss() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - - let section = object.section_id(write::StandardSection::UninitializedData); - - let symbol = object.add_symbol(write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 18, 4); - - let symbol = object.add_symbol(write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 34, 8); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"bss.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let bss = sections.next().unwrap(); - println!("{:?}", bss); - let bss_index = bss.index(); - assert_eq!(bss.name(), Ok(".bss")); - assert_eq!(bss.kind(), SectionKind::UninitializedData); - assert_eq!(bss.size(), 58); - assert_eq!(bss.data(), Ok(&[][..])); - - let section = sections.next(); - assert!(section.is_none(), "unexpected section {:?}", section); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 24); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} - -#[test] -fn elf_x86_64_bss() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let section = object.section_id(write::StandardSection::UninitializedData); - - let symbol = object.add_symbol(write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 18, 4); - - let symbol = object.add_symbol(write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 34, 8); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"bss.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok("")); - assert_eq!(section.kind(), SectionKind::Metadata); - assert_eq!(section.address(), 0); - assert_eq!(section.size(), 0); - - let bss = sections.next().unwrap(); - println!("{:?}", bss); - let bss_index = bss.index(); - assert_eq!(bss.name(), Ok(".bss")); - assert_eq!(bss.kind(), SectionKind::UninitializedData); - assert_eq!(bss.size(), 58); - assert_eq!(bss.data(), Ok(&[][..])); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("")); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 18); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 24); - assert_eq!(symbol.size(), 34); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} - -#[test] -fn macho_x86_64_bss() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - let section = object.section_id(write::StandardSection::UninitializedData); - - let symbol = object.add_symbol(write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 18, 4); - - let symbol = object.add_symbol(write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 34, 8); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"bss.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let bss = sections.next().unwrap(); - println!("{:?}", bss); - let bss_index = bss.index(); - assert_eq!(bss.name(), Ok("__bss")); - assert_eq!(bss.segment_name(), Ok(Some("__DATA"))); - assert_eq!(bss.kind(), SectionKind::UninitializedData); - assert_eq!(bss.size(), 58); - assert_eq!(bss.data(), Ok(&[][..])); - - let section = sections.next(); - assert!(section.is_none(), "unexpected section {:?}", section); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 24); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} diff --git a/vendor/object/tests/round_trip/coff.rs b/vendor/object/tests/round_trip/coff.rs deleted file mode 100644 index 6785dc3..0000000 --- a/vendor/object/tests/round_trip/coff.rs +++ /dev/null @@ -1,56 +0,0 @@ -use object::read::{Object, ObjectSection}; -use object::{read, write}; -use object::{ - Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SymbolFlags, - SymbolKind, SymbolScope, -}; - -#[test] -fn reloc_overflow() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[0; 4], 4); - let symbol = object.add_symbol(write::Symbol { - name: b"f".to_vec(), - value: 0, - size: 4, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - for i in 0..0x10000 { - object - .add_relocation( - text, - write::Relocation { - offset: i, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol, - addend: 0, - }, - ) - .unwrap(); - } - let bytes = object.write().unwrap(); - - //std::fs::write(&"reloc_overflow.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let section = object.sections().next().unwrap(); - assert_eq!(section.name(), Ok(".text")); - - let mut i = 0; - for (offset, _relocation) in section.relocations() { - assert_eq!(offset, i); - i += 1; - } - assert_eq!(i, 0x10000); -} diff --git a/vendor/object/tests/round_trip/comdat.rs b/vendor/object/tests/round_trip/comdat.rs deleted file mode 100644 index 7b697a0..0000000 --- a/vendor/object/tests/round_trip/comdat.rs +++ /dev/null @@ -1,225 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::pe; -use object::read::{Object, ObjectComdat, ObjectSection, ObjectSymbol}; -use object::{read, write}; -use object::{ - Architecture, BinaryFormat, ComdatKind, Endianness, SectionKind, SymbolFlags, SymbolKind, - SymbolScope, -}; - -#[test] -fn coff_x86_64_comdat() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - - let (section1, offset) = - object.add_subsection(write::StandardSection::Text, b"s1", &[0, 1, 2, 3], 4); - object.section_symbol(section1); - let (section2, _) = - object.add_subsection(write::StandardSection::Data, b"s1", &[0, 1, 2, 3], 4); - object.section_symbol(section2); - - let symbol = object.add_symbol(write::Symbol { - name: b"s1".to_vec(), - value: offset, - size: 4, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(section1), - flags: SymbolFlags::None, - }); - - object.add_comdat(write::Comdat { - kind: ComdatKind::NoDuplicates, - symbol, - sections: vec![section1, section2], - }); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"comdat.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let section1 = sections.next().unwrap(); - println!("{:?}", section1); - let section1_index = section1.index(); - assert_eq!(section1.name(), Ok(".text$s1")); - assert_eq!(section1.kind(), SectionKind::Text); - assert_eq!(section1.address(), 0); - assert_eq!(section1.size(), 4); - - let section2 = sections.next().unwrap(); - println!("{:?}", section2); - let section2_index = section2.index(); - assert_eq!(section2.name(), Ok(".data$s1")); - assert_eq!(section2.kind(), SectionKind::Data); - assert_eq!(section2.address(), 0); - assert_eq!(section2.size(), 4); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok(".text$s1")); - assert_eq!(symbol.kind(), SymbolKind::Section); - assert_eq!( - symbol.section(), - read::SymbolSection::Section(section1.index()) - ); - assert_eq!( - symbol.flags(), - SymbolFlags::CoffSection { - selection: pe::IMAGE_COMDAT_SELECT_NODUPLICATES, - associative_section: None - } - ); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok(".data$s1")); - assert_eq!(symbol.kind(), SymbolKind::Section); - assert_eq!( - symbol.section(), - read::SymbolSection::Section(section2.index()) - ); - assert_eq!( - symbol.flags(), - SymbolFlags::CoffSection { - selection: pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE, - associative_section: Some(section1_index) - } - ); - - let symbol = symbols.next().unwrap(); - let symbol_index = symbol.index(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("s1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!( - symbol.section(), - read::SymbolSection::Section(section1.index()) - ); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); - - let mut comdats = object.comdats(); - - let comdat = comdats.next().unwrap(); - println!("{:?}", comdat); - assert_eq!(comdat.kind(), ComdatKind::NoDuplicates); - assert_eq!(comdat.symbol(), symbol_index); - - let mut comdat_sections = comdat.sections(); - assert_eq!(comdat_sections.next(), Some(section1_index)); - assert_eq!(comdat_sections.next(), Some(section2_index)); - assert_eq!(comdat_sections.next(), None); -} - -#[test] -fn elf_x86_64_comdat() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let (section1, offset) = - object.add_subsection(write::StandardSection::Text, b"s1", &[0, 1, 2, 3], 4); - let (section2, _) = - object.add_subsection(write::StandardSection::Data, b"s1", &[0, 1, 2, 3], 4); - - let symbol = object.add_symbol(write::Symbol { - name: b"s1".to_vec(), - value: offset, - size: 4, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(section1), - flags: SymbolFlags::None, - }); - - object.add_comdat(write::Comdat { - kind: ComdatKind::Any, - symbol, - sections: vec![section1, section2], - }); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"comdat.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok("")); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok(".group")); - - let section1 = sections.next().unwrap(); - println!("{:?}", section1); - let section1_index = section1.index(); - assert_eq!(section1.name(), Ok(".text.s1")); - assert_eq!(section1.kind(), SectionKind::Text); - assert_eq!(section1.address(), 0); - assert_eq!(section1.size(), 4); - - let section2 = sections.next().unwrap(); - println!("{:?}", section2); - let section2_index = section2.index(); - assert_eq!(section2.name(), Ok(".data.s1")); - assert_eq!(section2.kind(), SectionKind::Data); - assert_eq!(section2.address(), 0); - assert_eq!(section2.size(), 4); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("")); - - let symbol = symbols.next().unwrap(); - let symbol_index = symbol.index(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("s1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!( - symbol.section(), - read::SymbolSection::Section(section1.index()) - ); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); - - let mut comdats = object.comdats(); - - let comdat = comdats.next().unwrap(); - println!("{:?}", comdat); - assert_eq!(comdat.kind(), ComdatKind::Any); - assert_eq!(comdat.symbol(), symbol_index); - - let mut comdat_sections = comdat.sections(); - assert_eq!(comdat_sections.next(), Some(section1_index)); - assert_eq!(comdat_sections.next(), Some(section2_index)); - assert_eq!(comdat_sections.next(), None); -} diff --git a/vendor/object/tests/round_trip/common.rs b/vendor/object/tests/round_trip/common.rs deleted file mode 100644 index 74d4438..0000000 --- a/vendor/object/tests/round_trip/common.rs +++ /dev/null @@ -1,245 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::read::{Object, ObjectSection, ObjectSymbol}; -use object::{read, write}; -use object::{ - Architecture, BinaryFormat, Endianness, SectionKind, SymbolFlags, SymbolKind, SymbolScope, -}; - -#[test] -fn coff_x86_64_common() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - - let symbol = write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 4, 4); - - let symbol = write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 8, 8); - - // Also check undefined symbols, which are very similar. - let symbol = write::Symbol { - name: b"v3".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_symbol(symbol); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"common.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section(), read::SymbolSection::Common); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 4); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section(), read::SymbolSection::Common); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 8); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v3")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section(), read::SymbolSection::Undefined); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), true); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 0); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} - -#[test] -fn elf_x86_64_common() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let symbol = write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 4, 4); - - let symbol = write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 8, 8); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"common.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("")); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section(), read::SymbolSection::Common); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 4); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section(), read::SymbolSection::Common); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.size(), 8); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} - -#[test] -fn macho_x86_64_common() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - let symbol = write::Symbol { - name: b"v1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 4, 4); - - let symbol = write::Symbol { - name: b"v2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Data, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }; - object.add_common_symbol(symbol, 8, 8); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"common.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let common = sections.next().unwrap(); - println!("{:?}", common); - let common_index = common.index(); - assert_eq!(common.name(), Ok("__common")); - assert_eq!(common.segment_name(), Ok(Some("__DATA"))); - assert_eq!(common.kind(), SectionKind::Common); - assert_eq!(common.size(), 16); - assert_eq!(common.data(), Ok(&[][..])); - - let section = sections.next(); - assert!(section.is_none(), "unexpected section {:?}", section); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_v1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(common_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 0); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_v2")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(common_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.address(), 8); - - let symbol = symbols.next(); - assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); -} diff --git a/vendor/object/tests/round_trip/elf.rs b/vendor/object/tests/round_trip/elf.rs deleted file mode 100644 index 0aafadc..0000000 --- a/vendor/object/tests/round_trip/elf.rs +++ /dev/null @@ -1,289 +0,0 @@ -use object::read::elf::{FileHeader, SectionHeader}; -use object::read::{Object, ObjectSection, ObjectSymbol}; -use object::{ - elf, read, write, Architecture, BinaryFormat, Endianness, LittleEndian, SectionIndex, - SectionKind, SymbolFlags, SymbolKind, SymbolScope, SymbolSection, U32, -}; -use std::io::Write; - -#[test] -fn symtab_shndx() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - for i in 0..0x10000 { - let name = format!("func{}", i).into_bytes(); - let (section, offset) = - object.add_subsection(write::StandardSection::Text, &name, &[0xcc], 1); - object.add_symbol(write::Symbol { - name, - value: offset, - size: 1, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(section), - flags: SymbolFlags::None, - }); - } - let bytes = object.write().unwrap(); - - //std::fs::write(&"symtab_shndx.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - for symbol in object.symbols().skip(1) { - assert_eq!( - symbol.section(), - SymbolSection::Section(SectionIndex(symbol.index().0)) - ); - } -} - -#[test] -fn aligned_sections() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let text_section_id = object.add_section(vec![], b".text".to_vec(), SectionKind::Text); - let text_section = object.section_mut(text_section_id); - text_section.set_data(&[][..], 4096); - - let data_section_id = object.add_section(vec![], b".data".to_vec(), SectionKind::Data); - let data_section = object.section_mut(data_section_id); - data_section.set_data(&b"1234"[..], 16); - - let bytes = object.write().unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - let _ = sections.next().unwrap(); - - let section = sections.next().unwrap(); - assert_eq!(section.name(), Ok(".text")); - assert_eq!(section.file_range(), Some((4096, 0))); - - let section = sections.next().unwrap(); - assert_eq!(section.name(), Ok(".data")); - assert_eq!(section.file_range(), Some((4096, 4))); -} - -#[cfg(feature = "compression")] -#[test] -fn compression_zlib() { - use object::read::ObjectSection; - use object::LittleEndian as LE; - - let data = b"test data data data"; - let len = data.len() as u64; - - let mut ch = object::elf::CompressionHeader64::::default(); - ch.ch_type.set(LE, object::elf::ELFCOMPRESS_ZLIB); - ch.ch_size.set(LE, len); - ch.ch_addralign.set(LE, 1); - - let mut buf = Vec::new(); - buf.write(object::bytes_of(&ch)).unwrap(); - let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); - encoder.write_all(data).unwrap(); - let compressed = encoder.finish().unwrap(); - - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - let section = object.add_section( - Vec::new(), - b".debug_info".to_vec(), - object::SectionKind::Other, - ); - object.section_mut(section).set_data(compressed, 1); - object.section_mut(section).flags = object::SectionFlags::Elf { - sh_flags: object::elf::SHF_COMPRESSED.into(), - }; - let bytes = object.write().unwrap(); - - //std::fs::write(&"compression.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let section = object.section_by_name(".debug_info").unwrap(); - let uncompressed = section.uncompressed_data().unwrap(); - assert_eq!(data, &*uncompressed); -} - -#[cfg(feature = "compression")] -#[test] -fn compression_gnu() { - use object::read::ObjectSection; - use std::io::Write; - - let data = b"test data data data"; - let len = data.len() as u32; - - let mut buf = Vec::new(); - buf.write_all(b"ZLIB\0\0\0\0").unwrap(); - buf.write_all(&len.to_be_bytes()).unwrap(); - let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); - encoder.write_all(data).unwrap(); - let compressed = encoder.finish().unwrap(); - - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - let section = object.add_section( - Vec::new(), - b".zdebug_info".to_vec(), - object::SectionKind::Other, - ); - object.section_mut(section).set_data(compressed, 1); - let bytes = object.write().unwrap(); - - //std::fs::write(&"compression.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let section = object.section_by_name(".zdebug_info").unwrap(); - let uncompressed = section.uncompressed_data().unwrap(); - assert_eq!(data, &*uncompressed); -} - -#[test] -fn note() { - let endian = Endianness::Little; - let mut object = write::Object::new(BinaryFormat::Elf, Architecture::X86_64, endian); - - // Add note section with align = 4. - let mut buffer = Vec::new(); - - buffer - .write(object::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(endian, 6), - n_descsz: U32::new(endian, 11), - n_type: U32::new(endian, 1), - })) - .unwrap(); - buffer.write(b"name1\0\0\0").unwrap(); - buffer.write(b"descriptor\0\0").unwrap(); - - buffer - .write(object::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(endian, 6), - n_descsz: U32::new(endian, 11), - n_type: U32::new(endian, 2), - })) - .unwrap(); - buffer.write(b"name2\0\0\0").unwrap(); - buffer.write(b"descriptor\0\0").unwrap(); - - let section = object.add_section(Vec::new(), b".note4".to_vec(), SectionKind::Note); - object.section_mut(section).set_data(buffer, 4); - - // Add note section with align = 8. - let mut buffer = Vec::new(); - - buffer - .write(object::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(endian, 6), - n_descsz: U32::new(endian, 11), - n_type: U32::new(endian, 1), - })) - .unwrap(); - buffer.write(b"name1\0\0\0\0\0\0\0").unwrap(); - buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); - - buffer - .write(object::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(endian, 4), - n_descsz: U32::new(endian, 11), - n_type: U32::new(endian, 2), - })) - .unwrap(); - buffer.write(b"abc\0").unwrap(); - buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); - - let section = object.add_section(Vec::new(), b".note8".to_vec(), SectionKind::Note); - object.section_mut(section).set_data(buffer, 8); - - let bytes = &*object.write().unwrap(); - - //std::fs::write(&"note.o", &bytes).unwrap(); - - let header = elf::FileHeader64::parse(bytes).unwrap(); - let endian: LittleEndian = header.endian().unwrap(); - let sections = header.sections(endian, bytes).unwrap(); - - let section = sections.section(SectionIndex(1)).unwrap(); - assert_eq!(sections.section_name(endian, section).unwrap(), b".note4"); - assert_eq!(section.sh_addralign(endian), 4); - let mut notes = section.notes(endian, bytes).unwrap().unwrap(); - let note = notes.next().unwrap().unwrap(); - assert_eq!(note.name(), b"name1"); - assert_eq!(note.desc(), b"descriptor\0"); - assert_eq!(note.n_type(endian), 1); - let note = notes.next().unwrap().unwrap(); - assert_eq!(note.name(), b"name2"); - assert_eq!(note.desc(), b"descriptor\0"); - assert_eq!(note.n_type(endian), 2); - assert!(notes.next().unwrap().is_none()); - - let section = sections.section(SectionIndex(2)).unwrap(); - assert_eq!(sections.section_name(endian, section).unwrap(), b".note8"); - assert_eq!(section.sh_addralign(endian), 8); - let mut notes = section.notes(endian, bytes).unwrap().unwrap(); - let note = notes.next().unwrap().unwrap(); - assert_eq!(note.name(), b"name1"); - assert_eq!(note.desc(), b"descriptor\0"); - assert_eq!(note.n_type(endian), 1); - let note = notes.next().unwrap().unwrap(); - assert_eq!(note.name(), b"abc"); - assert_eq!(note.desc(), b"descriptor\0"); - assert_eq!(note.n_type(endian), 2); - assert!(notes.next().unwrap().is_none()); -} - -#[test] -fn gnu_property() { - gnu_property_inner::>(Architecture::I386); - gnu_property_inner::>(Architecture::X86_64); -} - -fn gnu_property_inner>(architecture: Architecture) { - let endian = Endianness::Little; - let mut object = write::Object::new(BinaryFormat::Elf, architecture, endian); - object.add_elf_gnu_property_u32( - elf::GNU_PROPERTY_X86_FEATURE_1_AND, - elf::GNU_PROPERTY_X86_FEATURE_1_IBT | elf::GNU_PROPERTY_X86_FEATURE_1_SHSTK, - ); - - let bytes = &*object.write().unwrap(); - - //std::fs::write(&"note.o", &bytes).unwrap(); - - let header = Elf::parse(bytes).unwrap(); - assert_eq!(header.endian().unwrap(), endian); - let sections = header.sections(endian, bytes).unwrap(); - let section = sections.section(SectionIndex(1)).unwrap(); - assert_eq!( - sections.section_name(endian, section).unwrap(), - b".note.gnu.property" - ); - assert_eq!(section.sh_flags(endian).into(), u64::from(elf::SHF_ALLOC)); - let mut notes = section.notes(endian, bytes).unwrap().unwrap(); - let note = notes.next().unwrap().unwrap(); - let mut props = note.gnu_properties(endian).unwrap(); - let prop = props.next().unwrap().unwrap(); - assert_eq!(prop.pr_type(), elf::GNU_PROPERTY_X86_FEATURE_1_AND); - assert_eq!( - prop.data_u32(endian).unwrap(), - elf::GNU_PROPERTY_X86_FEATURE_1_IBT | elf::GNU_PROPERTY_X86_FEATURE_1_SHSTK - ); - assert!(props.next().unwrap().is_none()); - assert!(notes.next().unwrap().is_none()); -} diff --git a/vendor/object/tests/round_trip/macho.rs b/vendor/object/tests/round_trip/macho.rs deleted file mode 100644 index 1aa8156..0000000 --- a/vendor/object/tests/round_trip/macho.rs +++ /dev/null @@ -1,64 +0,0 @@ -use object::read::macho::MachHeader; -use object::read::{Object, ObjectSection}; -use object::{macho, read, write, Architecture, BinaryFormat, Endianness}; - -// Test that segment size is valid when the first section needs alignment. -#[test] -fn issue_286_segment_file_size() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[1; 30], 0x1000); - - let bytes = &*object.write().unwrap(); - let header = macho::MachHeader64::parse(bytes, 0).unwrap(); - let endian: Endianness = header.endian().unwrap(); - let mut commands = header.load_commands(endian, bytes, 0).unwrap(); - let command = commands.next().unwrap().unwrap(); - let (segment, _) = command.segment_64().unwrap().unwrap(); - assert_eq!(segment.vmsize.get(endian), 30); - assert_eq!(segment.filesize.get(endian), 30); -} - -// We were emitting section file alignment padding that didn't match the address alignment padding. -#[test] -fn issue_552_section_file_alignment() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - // The starting file offset is not a multiple of 32 (checked later). - // Length of 32 ensures that the file offset of the end of this section is still not a - // multiple of 32. - let section = object.add_section(vec![], vec![], object::SectionKind::ReadOnlyDataWithRel); - object.append_section_data(section, &vec![0u8; 32], 1); - - // Address is already aligned correctly, so there must not any padding, - // even though file offset is not aligned. - let section = object.add_section(vec![], vec![], object::SectionKind::ReadOnlyData); - object.append_section_data(section, &vec![0u8; 1], 32); - - let bytes = &*object.write().unwrap(); - //std::fs::write(&"align.o", &bytes).unwrap(); - let object = read::File::parse(bytes).unwrap(); - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - let offset = section.file_range().unwrap().0; - // Check file offset is not aligned to 32. - assert_ne!(offset % 32, 0); - assert_eq!(section.address(), 0); - assert_eq!(section.size(), 32); - - let section = sections.next().unwrap(); - // Check there is no padding. - assert_eq!(section.file_range(), Some((offset + 32, 1))); - assert_eq!(section.address(), 32); - assert_eq!(section.size(), 1); -} diff --git a/vendor/object/tests/round_trip/mod.rs b/vendor/object/tests/round_trip/mod.rs deleted file mode 100644 index b92a94a..0000000 --- a/vendor/object/tests/round_trip/mod.rs +++ /dev/null @@ -1,686 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::read::{Object, ObjectSection, ObjectSymbol}; -use object::{read, write, SectionIndex, SubArchitecture}; -use object::{ - Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind, - SymbolFlags, SymbolKind, SymbolScope, SymbolSection, -}; - -mod bss; -mod coff; -mod comdat; -mod common; -mod elf; -mod macho; -mod section_flags; -mod tls; - -#[test] -fn coff_any() { - for (arch, sub_arch) in [ - (Architecture::Aarch64, None), - (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), - (Architecture::Arm, None), - (Architecture::I386, None), - (Architecture::X86_64, None), - ] - .iter() - .copied() - { - let mut object = write::Object::new(BinaryFormat::Coff, arch, Endianness::Little); - object.set_sub_architecture(sub_arch); - - object.add_file_symbol(b"file.c".to_vec()); - - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[1; 30], 4); - - let func1_offset = object.append_section_data(text, &[1; 30], 4); - assert_eq!(func1_offset, 32); - let func1_symbol = object.add_symbol(write::Symbol { - name: b"func1".to_vec(), - value: func1_offset, - size: 32, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - let func2_offset = object.append_section_data(text, &[1; 30], 4); - assert_eq!(func2_offset, 64); - object.add_symbol(write::Symbol { - name: b"func2_long".to_vec(), - value: func2_offset, - size: 32, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - object - .add_relocation( - text, - write::Relocation { - offset: 8, - size: arch.address_size().unwrap().bytes() * 8, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: func1_symbol, - addend: 0, - }, - ) - .unwrap(); - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), arch); - assert_eq!(object.sub_architecture(), sub_arch); - assert_eq!(object.endianness(), Endianness::Little); - - let mut sections = object.sections(); - - let text = sections.next().unwrap(); - println!("{:?}", text); - let text_index = text.index(); - assert_eq!(text.name(), Ok(".text")); - assert_eq!(text.kind(), SectionKind::Text); - assert_eq!(text.address(), 0); - assert_eq!(text.size(), 94); - assert_eq!(&text.data().unwrap()[..30], &[1; 30]); - assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("file.c")); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.kind(), SymbolKind::File); - assert_eq!(symbol.section(), SymbolSection::None); - assert_eq!(symbol.scope(), SymbolScope::Compilation); - assert_eq!(symbol.is_weak(), false); - - let decorated_name = |name: &str| { - if arch == Architecture::I386 { - format!("_{name}") - } else { - name.to_owned() - } - }; - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let func1_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok(decorated_name("func1").as_str())); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.kind(), SymbolKind::Text); - assert_eq!(symbol.section_index(), Some(text_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok(decorated_name("func2_long").as_str())); - assert_eq!(symbol.address(), func2_offset); - assert_eq!(symbol.kind(), SymbolKind::Text); - assert_eq!(symbol.section_index(), Some(text_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let mut relocations = text.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), arch.address_size().unwrap().bytes() * 8); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(func1_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let map = object.symbol_map(); - let symbol = map.get(func1_offset + 1).unwrap(); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.name(), decorated_name("func1")); - assert_eq!(map.get(func1_offset - 1), None); - } -} - -#[test] -fn elf_x86_64() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - object.add_file_symbol(b"file.c".to_vec()); - - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[1; 30], 4); - - let func1_offset = object.append_section_data(text, &[1; 30], 4); - assert_eq!(func1_offset, 32); - let func1_symbol = object.add_symbol(write::Symbol { - name: b"func1".to_vec(), - value: func1_offset, - size: 32, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - object - .add_relocation( - text, - write::Relocation { - offset: 8, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: func1_symbol, - addend: 0, - }, - ) - .unwrap(); - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - assert_eq!(object.endianness(), Endianness::Little); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok("")); - assert_eq!(section.kind(), SectionKind::Metadata); - assert_eq!(section.address(), 0); - assert_eq!(section.size(), 0); - - let text = sections.next().unwrap(); - println!("{:?}", text); - let text_index = text.index(); - assert_eq!(text.name(), Ok(".text")); - assert_eq!(text.kind(), SectionKind::Text); - assert_eq!(text.address(), 0); - assert_eq!(text.size(), 62); - assert_eq!(&text.data().unwrap()[..30], &[1; 30]); - assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("")); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.kind(), SymbolKind::Null); - assert_eq!(symbol.section_index(), None); - assert_eq!(symbol.scope(), SymbolScope::Unknown); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), true); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("file.c")); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.kind(), SymbolKind::File); - assert_eq!(symbol.section(), SymbolSection::None); - assert_eq!(symbol.scope(), SymbolScope::Compilation); - assert_eq!(symbol.is_weak(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let func1_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("func1")); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.kind(), SymbolKind::Text); - assert_eq!(symbol.section_index(), Some(text_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let mut relocations = text.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(func1_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let map = object.symbol_map(); - let symbol = map.get(func1_offset + 1).unwrap(); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.name(), "func1"); - assert_eq!(map.get(func1_offset - 1), None); -} - -#[test] -fn elf_any() { - for (arch, endian) in [ - (Architecture::Aarch64, Endianness::Little), - (Architecture::Aarch64_Ilp32, Endianness::Little), - (Architecture::Arm, Endianness::Little), - (Architecture::Avr, Endianness::Little), - (Architecture::Bpf, Endianness::Little), - (Architecture::Csky, Endianness::Little), - (Architecture::I386, Endianness::Little), - (Architecture::X86_64, Endianness::Little), - (Architecture::X86_64_X32, Endianness::Little), - (Architecture::Hexagon, Endianness::Little), - (Architecture::LoongArch64, Endianness::Little), - (Architecture::Mips, Endianness::Little), - (Architecture::Mips64, Endianness::Little), - (Architecture::Msp430, Endianness::Little), - (Architecture::PowerPc, Endianness::Big), - (Architecture::PowerPc64, Endianness::Big), - (Architecture::Riscv32, Endianness::Little), - (Architecture::Riscv64, Endianness::Little), - (Architecture::S390x, Endianness::Big), - (Architecture::Sbf, Endianness::Little), - (Architecture::Sparc64, Endianness::Big), - (Architecture::Xtensa, Endianness::Little), - ] - .iter() - .copied() - { - let mut object = write::Object::new(BinaryFormat::Elf, arch, endian); - - let section = object.section_id(write::StandardSection::Data); - object.append_section_data(section, &[1; 30], 4); - let symbol = object.section_symbol(section); - - object - .add_relocation( - section, - write::Relocation { - offset: 8, - size: 32, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol, - addend: 0, - }, - ) - .unwrap(); - if arch.address_size().unwrap().bytes() >= 8 { - object - .add_relocation( - section, - write::Relocation { - offset: 16, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol, - addend: 0, - }, - ) - .unwrap(); - } - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - println!("{:?}", object.architecture()); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), arch); - assert_eq!(object.endianness(), endian); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok("")); - assert_eq!(section.kind(), SectionKind::Metadata); - assert_eq!(section.address(), 0); - assert_eq!(section.size(), 0); - - let data = sections.next().unwrap(); - println!("{:?}", data); - assert_eq!(data.name(), Ok(".data")); - assert_eq!(data.kind(), SectionKind::Data); - - let mut relocations = data.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 32); - assert_eq!(relocation.addend(), 0); - - if arch.address_size().unwrap().bytes() >= 8 { - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 16); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!(relocation.addend(), 0); - } - } -} - -#[test] -fn macho_x86_64() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - object.add_file_symbol(b"file.c".to_vec()); - - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[1; 30], 4); - - let func1_offset = object.append_section_data(text, &[1; 30], 4); - assert_eq!(func1_offset, 32); - let func1_symbol = object.add_symbol(write::Symbol { - name: b"func1".to_vec(), - value: func1_offset, - size: 32, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - object - .add_relocation( - text, - write::Relocation { - offset: 8, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: func1_symbol, - addend: 0, - }, - ) - .unwrap(); - object - .add_relocation( - text, - write::Relocation { - offset: 16, - size: 32, - kind: RelocationKind::Relative, - encoding: RelocationEncoding::Generic, - symbol: func1_symbol, - addend: -4, - }, - ) - .unwrap(); - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), Architecture::X86_64); - assert_eq!(object.endianness(), Endianness::Little); - - let mut sections = object.sections(); - - let text = sections.next().unwrap(); - println!("{:?}", text); - let text_index = text.index(); - assert_eq!(text.name(), Ok("__text")); - assert_eq!(text.segment_name(), Ok(Some("__TEXT"))); - assert_eq!(text.kind(), SectionKind::Text); - assert_eq!(text.address(), 0); - assert_eq!(text.size(), 62); - assert_eq!(&text.data().unwrap()[..30], &[1; 30]); - assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let func1_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("_func1")); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.kind(), SymbolKind::Text); - assert_eq!(symbol.section_index(), Some(text_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let mut relocations = text.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(func1_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 16); - assert_eq!(relocation.kind(), RelocationKind::Relative); - assert_eq!(relocation.encoding(), RelocationEncoding::X86RipRelative); - assert_eq!(relocation.size(), 32); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(func1_symbol) - ); - assert_eq!(relocation.addend(), -4); - - let map = object.symbol_map(); - let symbol = map.get(func1_offset + 1).unwrap(); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.name(), "_func1"); - assert_eq!(map.get(func1_offset - 1), None); -} - -#[test] -fn macho_any() { - for (arch, subarch, endian) in [ - (Architecture::Aarch64, None, Endianness::Little), - ( - Architecture::Aarch64, - Some(SubArchitecture::Arm64E), - Endianness::Little, - ), - (Architecture::Aarch64_Ilp32, None, Endianness::Little), - /* TODO: - (Architecture::Arm, None, Endianness::Little), - */ - (Architecture::I386, None, Endianness::Little), - (Architecture::X86_64, None, Endianness::Little), - /* TODO: - (Architecture::PowerPc, None, Endianness::Big), - (Architecture::PowerPc64, None, Endianness::Big), - */ - ] - .iter() - .copied() - { - let mut object = write::Object::new(BinaryFormat::MachO, arch, endian); - object.set_sub_architecture(subarch); - - let section = object.section_id(write::StandardSection::Data); - object.append_section_data(section, &[1; 30], 4); - let symbol = object.section_symbol(section); - - object - .add_relocation( - section, - write::Relocation { - offset: 8, - size: 32, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol, - addend: 0, - }, - ) - .unwrap(); - if arch.address_size().unwrap().bytes() >= 8 { - object - .add_relocation( - section, - write::Relocation { - offset: 16, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol, - addend: 0, - }, - ) - .unwrap(); - } - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - println!("{:?}", object.architecture()); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), arch); - assert_eq!(object.sub_architecture(), subarch); - assert_eq!(object.endianness(), endian); - - let mut sections = object.sections(); - - let data = sections.next().unwrap(); - println!("{:?}", data); - assert_eq!(data.segment_name(), Ok(Some("__DATA"))); - assert_eq!(data.name(), Ok("__data")); - assert_eq!(data.kind(), SectionKind::Data); - - let mut relocations = data.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 32); - assert_eq!(relocation.addend(), 0); - - if arch.address_size().unwrap().bytes() >= 8 { - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 16); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!(relocation.addend(), 0); - } - } -} - -#[cfg(feature = "xcoff")] -#[test] -fn xcoff_powerpc() { - for arch in [Architecture::PowerPc, Architecture::PowerPc64] { - let mut object = write::Object::new(BinaryFormat::Xcoff, arch, Endianness::Big); - - object.add_file_symbol(b"file.c".to_vec()); - - let text = object.section_id(write::StandardSection::Text); - object.append_section_data(text, &[1; 30], 4); - - let func1_offset = object.append_section_data(text, &[1; 30], 4); - assert_eq!(func1_offset, 32); - let func1_symbol = object.add_symbol(write::Symbol { - name: b"func1".to_vec(), - value: func1_offset, - size: 32, - kind: SymbolKind::Text, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Section(text), - flags: SymbolFlags::None, - }); - - object - .add_relocation( - text, - write::Relocation { - offset: 8, - size: 64, - kind: RelocationKind::Absolute, - encoding: RelocationEncoding::Generic, - symbol: func1_symbol, - addend: 0, - }, - ) - .unwrap(); - - let bytes = object.write().unwrap(); - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Xcoff); - assert_eq!(object.architecture(), arch); - assert_eq!(object.endianness(), Endianness::Big); - - let mut sections = object.sections(); - - let text = sections.next().unwrap(); - println!("{:?}", text); - let text_index = text.index().0; - assert_eq!(text.name(), Ok(".text")); - assert_eq!(text.kind(), SectionKind::Text); - assert_eq!(text.address(), 0); - assert_eq!(text.size(), 62); - assert_eq!(&text.data().unwrap()[..30], &[1; 30]); - assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); - - let mut symbols = object.symbols(); - - let mut symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("file.c")); - assert_eq!(symbol.address(), 0); - assert_eq!(symbol.kind(), SymbolKind::File); - assert_eq!(symbol.section_index(), None); - assert_eq!(symbol.scope(), SymbolScope::Compilation); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let func1_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("func1")); - assert_eq!(symbol.address(), func1_offset); - assert_eq!(symbol.kind(), SymbolKind::Text); - assert_eq!(symbol.section_index(), Some(SectionIndex(text_index))); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let mut relocations = text.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 8); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(func1_symbol) - ); - assert_eq!(relocation.addend(), 0); - } -} diff --git a/vendor/object/tests/round_trip/section_flags.rs b/vendor/object/tests/round_trip/section_flags.rs deleted file mode 100644 index b1ca398..0000000 --- a/vendor/object/tests/round_trip/section_flags.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::read::{Object, ObjectSection}; -use object::{read, write}; -use object::{Architecture, BinaryFormat, Endianness, SectionFlags, SectionKind}; - -#[test] -fn coff_x86_64_section_flags() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - - let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); - object.section_mut(section).flags = SectionFlags::Coff { - characteristics: object::pe::IMAGE_SCN_MEM_WRITE, - }; - - let bytes = object.write().unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - let section = sections.next().unwrap(); - assert_eq!(section.name(), Ok(".text")); - assert_eq!( - section.flags(), - SectionFlags::Coff { - characteristics: object::pe::IMAGE_SCN_MEM_WRITE | object::pe::IMAGE_SCN_ALIGN_1BYTES, - } - ); -} - -#[test] -fn elf_x86_64_section_flags() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); - object.section_mut(section).flags = SectionFlags::Elf { - sh_flags: object::elf::SHF_WRITE.into(), - }; - - let bytes = object.write().unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - sections.next().unwrap(); - let section = sections.next().unwrap(); - assert_eq!(section.name(), Ok(".text")); - assert_eq!( - section.flags(), - SectionFlags::Elf { - sh_flags: object::elf::SHF_WRITE.into(), - } - ); -} - -#[test] -fn macho_x86_64_section_flags() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); - object.section_mut(section).flags = SectionFlags::MachO { - flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, - }; - - let bytes = object.write().unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - let section = sections.next().unwrap(); - assert_eq!(section.name(), Ok(".text")); - assert_eq!( - section.flags(), - SectionFlags::MachO { - flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, - } - ); -} diff --git a/vendor/object/tests/round_trip/tls.rs b/vendor/object/tests/round_trip/tls.rs deleted file mode 100644 index 0af90bd..0000000 --- a/vendor/object/tests/round_trip/tls.rs +++ /dev/null @@ -1,316 +0,0 @@ -#![cfg(all(feature = "read", feature = "write"))] - -use object::read::{Object, ObjectSection, ObjectSymbol}; -use object::{read, write}; -use object::{ - Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind, - SymbolFlags, SymbolKind, SymbolScope, -}; - -#[test] -fn coff_x86_64_tls() { - let mut object = - write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); - - let section = object.section_id(write::StandardSection::Tls); - let symbol = object.add_symbol(write::Symbol { - name: b"tls1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_data(symbol, section, &[1; 30], 4); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"tls.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Coff); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - let tls_index = section.index(); - assert_eq!(section.name(), Ok(".tls$")); - assert_eq!(section.kind(), SectionKind::Data); - assert_eq!(section.size(), 30); - assert_eq!(§ion.data().unwrap()[..], &[1; 30]); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("tls1")); - assert_eq!(symbol.kind(), SymbolKind::Data); - assert_eq!(symbol.section_index(), Some(tls_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); -} - -#[test] -fn elf_x86_64_tls() { - let mut object = - write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); - - let section = object.section_id(write::StandardSection::Tls); - let symbol = object.add_symbol(write::Symbol { - name: b"tls1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_data(symbol, section, &[1; 30], 4); - - let section = object.section_id(write::StandardSection::UninitializedTls); - let symbol = object.add_symbol(write::Symbol { - name: b"tls2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 31, 4); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"tls.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::Elf); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let section = sections.next().unwrap(); - println!("{:?}", section); - assert_eq!(section.name(), Ok("")); - - let section = sections.next().unwrap(); - println!("{:?}", section); - let tdata_index = section.index(); - assert_eq!(section.name(), Ok(".tdata")); - assert_eq!(section.kind(), SectionKind::Tls); - assert_eq!(section.size(), 30); - assert_eq!(§ion.data().unwrap()[..], &[1; 30]); - - let section = sections.next().unwrap(); - println!("{:?}", section); - let tbss_index = section.index(); - assert_eq!(section.name(), Ok(".tbss")); - assert_eq!(section.kind(), SectionKind::UninitializedTls); - assert_eq!(section.size(), 31); - assert_eq!(§ion.data().unwrap()[..], &[]); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("")); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("tls1")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(tdata_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.size(), 30); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("tls2")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(tbss_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - assert_eq!(symbol.size(), 31); -} - -#[test] -fn macho_x86_64_tls() { - let mut object = write::Object::new( - BinaryFormat::MachO, - Architecture::X86_64, - Endianness::Little, - ); - - let section = object.section_id(write::StandardSection::Tls); - let symbol = object.add_symbol(write::Symbol { - name: b"tls1".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_data(symbol, section, &[1; 30], 4); - - let section = object.section_id(write::StandardSection::UninitializedTls); - let symbol = object.add_symbol(write::Symbol { - name: b"tls2".to_vec(), - value: 0, - size: 0, - kind: SymbolKind::Tls, - scope: SymbolScope::Linkage, - weak: false, - section: write::SymbolSection::Undefined, - flags: SymbolFlags::None, - }); - object.add_symbol_bss(symbol, section, 31, 4); - - let bytes = object.write().unwrap(); - - //std::fs::write(&"tls.o", &bytes).unwrap(); - - let object = read::File::parse(&*bytes).unwrap(); - assert_eq!(object.format(), BinaryFormat::MachO); - assert_eq!(object.architecture(), Architecture::X86_64); - - let mut sections = object.sections(); - - let thread_data = sections.next().unwrap(); - println!("{:?}", thread_data); - let thread_data_index = thread_data.index(); - assert_eq!(thread_data.name(), Ok("__thread_data")); - assert_eq!(thread_data.segment_name(), Ok(Some("__DATA"))); - assert_eq!(thread_data.kind(), SectionKind::Tls); - assert_eq!(thread_data.size(), 30); - assert_eq!(&thread_data.data().unwrap()[..], &[1; 30]); - - let thread_vars = sections.next().unwrap(); - println!("{:?}", thread_vars); - let thread_vars_index = thread_vars.index(); - assert_eq!(thread_vars.name(), Ok("__thread_vars")); - assert_eq!(thread_vars.segment_name(), Ok(Some("__DATA"))); - assert_eq!(thread_vars.kind(), SectionKind::TlsVariables); - assert_eq!(thread_vars.size(), 2 * 3 * 8); - assert_eq!(&thread_vars.data().unwrap()[..], &[0; 48][..]); - - let thread_bss = sections.next().unwrap(); - println!("{:?}", thread_bss); - let thread_bss_index = thread_bss.index(); - assert_eq!(thread_bss.name(), Ok("__thread_bss")); - assert_eq!(thread_bss.segment_name(), Ok(Some("__DATA"))); - assert_eq!(thread_bss.kind(), SectionKind::UninitializedTls); - assert_eq!(thread_bss.size(), 31); - assert_eq!(thread_bss.data(), Ok(&[][..])); - - let mut symbols = object.symbols(); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let tls1_init_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("_tls1$tlv$init")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(thread_data_index)); - assert_eq!(symbol.scope(), SymbolScope::Compilation); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let tls2_init_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("_tls2$tlv$init")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(thread_bss_index)); - assert_eq!(symbol.scope(), SymbolScope::Compilation); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_tls1")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(thread_vars_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - assert_eq!(symbol.name(), Ok("_tls2")); - assert_eq!(symbol.kind(), SymbolKind::Tls); - assert_eq!(symbol.section_index(), Some(thread_vars_index)); - assert_eq!(symbol.scope(), SymbolScope::Linkage); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), false); - - let symbol = symbols.next().unwrap(); - println!("{:?}", symbol); - let tlv_bootstrap_symbol = symbol.index(); - assert_eq!(symbol.name(), Ok("__tlv_bootstrap")); - assert_eq!(symbol.kind(), SymbolKind::Unknown); - assert_eq!(symbol.section_index(), None); - assert_eq!(symbol.scope(), SymbolScope::Unknown); - assert_eq!(symbol.is_weak(), false); - assert_eq!(symbol.is_undefined(), true); - - let mut relocations = thread_vars.relocations(); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 0); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(tlv_bootstrap_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 16); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(tls1_init_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 24); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(tlv_bootstrap_symbol) - ); - assert_eq!(relocation.addend(), 0); - - let (offset, relocation) = relocations.next().unwrap(); - println!("{:?}", relocation); - assert_eq!(offset, 40); - assert_eq!(relocation.kind(), RelocationKind::Absolute); - assert_eq!(relocation.encoding(), RelocationEncoding::Generic); - assert_eq!(relocation.size(), 64); - assert_eq!( - relocation.target(), - read::RelocationTarget::Symbol(tls2_init_symbol) - ); - assert_eq!(relocation.addend(), 0); -} -- cgit v1.2.3