├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── references ├── ELF.pdf ├── elf section的一些思考.pdf ├── 从零打造简单的SODUMP工具.pdf └── 简单粗暴的so加解密实现.pdf ├── src ├── ELFReader.cpp ├── ELFReader.h ├── ELFRebuilder.cpp ├── ELFRebuilder.h ├── Log.cpp ├── Log.h ├── elf.h ├── exutil.h └── main.cpp ├── test ├── libjiagu_AllDamage.so ├── libjiagu_PartDamage.so ├── libnative-lib_HandAllDamage.so ├── libnative-lib_HandPartDamage.so ├── libnative-lib_NoDamage.so └── libnative_NoDamage.so └── thinking ├── androidSO加载过程.md ├── elf修复思路.md ├── global_offset_table.png ├── global_offset_table2.png ├── plt.jpg └── symbol_hash_table.png /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore vscode setting 2 | .vscode 3 | 4 | # ignore compile output 5 | sb 6 | *.o 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This project develop platform have been changed to linux. 2 | # Because of some strange issuses with g++ parameter '-m32' under windows. 3 | 4 | CPP_SOURCES = $(wildcard src/*.cpp) 5 | HEADERS = $(wildcard src/*.h) 6 | 7 | OBJS = ${CPP_SOURCES:.cpp=.o} 8 | 9 | TARGET = sb 10 | 11 | CC = g++ 12 | ifeq ($(v), 64) 13 | CFLAGS = -g -std=c++11 -Wformat=0 14 | else 15 | CFLAGS = -g -std=c++11 -m32 16 | endif 17 | 18 | 19 | $(TARGET) : $(OBJS) 20 | $(CC) $(CFLAGS) $^ -o $@ 21 | 22 | %.o : %.cpp $(HEADERS) 23 | $(CC) $(CFLAGS) -c $< -o $@ 24 | 25 | 26 | # make clean cannot work under windows powershell or cmd 27 | # it report 28 | # # process_begin: CreateProcess(NULL, rm sb.exe src/main.o src/ELFReader.o, ...) failed. 29 | # # make (e=2): 系统找不到指定的文件。 30 | # # Makefile:23: recipe for target 'clean' failed 31 | # # make: *** [clean] Error 2 32 | # not because of rm under powershell need ',' to seperate each item. 33 | # I have tried that it didn't work yet. 34 | # 35 | # Thank to my friend help. I have try add double quote to the rm command. 36 | # But it shows 37 | # # "rm sb.exe src/main.o src/ELFReader.o" 38 | # # /usr/bin/bash: rm sb.exe src/main.o src/ELFReader.o: No such file or directory 39 | # # Makefile:30: recipe for target 'clean' failed 40 | # # make: *** [clean] Error 127 41 | # Don't know why it would enter bash from powershell. That mean wrong directory. 42 | # Google say it was because the PATH of "git/bin/bash" 43 | # I tried delete bash in git/bin. It show "make (e=2)" again. 44 | # 45 | # My suggestion is, just leave it...Don't use windows...(╯°□°)╯︵ ┻━┻ 46 | 47 | clean: 48 | rm $(TARGET) $(OBJS) 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # So Rebuilder 2 | 3 | This is a tool target at `.so` file repair, which section header has been damaged. 4 | 5 | Temporarily support 32bits-so-file. 6 | 7 | ## About this project 8 | 9 | To rebuild the section header. I learning a way to rebuild by the information of `segment` and `.dynamic` section from ThomasKing's article https://bbs.pediy.com/thread-192874.htm . 10 | 11 | Some reference articles I have placed in directory `reference` . 12 | 13 | And my ideas and some basing knowledge have placed in directory `thinking` . 14 | 15 | Some damaged so-file placed at `test` using for program testing. 16 | 17 | ## Usage 18 | You can run `make` command to compile this project. Then using `./sb -h` to see the help. 19 | 20 | The default compile environment is 32bits. 21 | If you want to compile 64bits version, you can run `make v=64`. 22 | What a shame that it doesn't support 64bits-so-file yet. 23 | 24 | ``` 25 | So Rebuilder --Powered by giglf 26 | usage: sb 27 | sb -o 28 | 29 | option: 30 | -o --output Specify the output file name. Or append "_repaired" default. 31 | -c --check Check the damage level and print it. 32 | -f --force Force to fully rebuild the section. 33 | -m --memso Source file is dump from memory from address x(hex) 34 | -v --verbose Print the verbose repair information 35 | -h --help Print this usage. 36 | -d --debug Print this program debug log. 37 | ``` 38 | 39 | The most common use is `./sb -c -d -v `. You can see all message output from repairing. 40 | The program may have bugs. Sometime it may have a wrong complete detection at damaged so-file. 41 | So I add a parameter. You can use `-f` or `--force` force to rebuild the so-file. 42 | 43 | If you find some bugs or have some questions. Please contact me. -------------------------------------------------------------------------------- /references/ELF.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/references/ELF.pdf -------------------------------------------------------------------------------- /references/elf section的一些思考.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/references/elf section的一些思考.pdf -------------------------------------------------------------------------------- /references/从零打造简单的SODUMP工具.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/references/从零打造简单的SODUMP工具.pdf -------------------------------------------------------------------------------- /references/简单粗暴的so加解密实现.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/references/简单粗暴的so加解密实现.pdf -------------------------------------------------------------------------------- /src/ELFReader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "ELFReader.h" 6 | #include "Log.h" 7 | #include "exutil.h" 8 | 9 | ELFReader::ELFReader(const char *filename) 10 | : filename(filename), inputFile(NULL), damageLevel(-1), didLoad(false), didRead(false), 11 | phdr_table(NULL), phdr_entrySize(0), phdr_num(0), phdr_size(0), 12 | midPart_start(0), midPart_end(0), midPart_size(0), 13 | shdr_table(NULL), shdr_entrySize(0), shdr_num(0), shdr_size(0), 14 | load_start(NULL), load_size(0), load_bias(0){ 15 | 16 | inputFile = fopen(filename, "rb"); 17 | if(inputFile == NULL){ 18 | ELOG("File \"%s\" open error.", filename); 19 | exit(EXIT_FAILURE); 20 | } 21 | } 22 | 23 | ELFReader::~ELFReader(){ 24 | if(load_start != NULL){ delete [](uint8_t*)load_start; } 25 | if(phdr_table != NULL){ delete [](uint8_t*)phdr_table; } 26 | if(midPart != NULL){ delete [](uint8_t*)midPart; } 27 | if(shdr_table != NULL){ delete [](uint8_t*)shdr_table; } 28 | } 29 | 30 | bool ELFReader::read(){ 31 | if(!(readElfHeader()&&verifyElfHeader()&&readProgramHeader())){ 32 | ELOG("so-file invalid."); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | // try to figure out which plan should use to repair the so-file. 37 | if(readSectionHeader()){ 38 | // damagelevel should set inside checkSectionHeader() 39 | checkSectionHeader(); 40 | if(!readOtherPart()){ 41 | ELOG("Read other part data failed."); 42 | exit(EXIT_FAILURE); 43 | } 44 | } else{ 45 | damageLevel = 2; 46 | } 47 | didRead = true; 48 | return true; 49 | } 50 | 51 | /** 52 | * load function should be called after readSofile() 53 | */ 54 | bool ELFReader::load(){ 55 | if(!didRead){ 56 | read(); 57 | } 58 | if(reserveAddressSpace() && loadSegments() && findPhdr()){ 59 | didLoad = true; 60 | return didLoad; 61 | } 62 | ELOG("Load segment failed."); 63 | exit(EXIT_FAILURE); 64 | } 65 | 66 | // Reserve a virtual address range big enough to hold all loadable 67 | // segments of a program header table. This is done by creating a 68 | // private anonymous mmap() with PROT_NONE. 69 | bool ELFReader::reserveAddressSpace(){ 70 | Elf_Addr min_vaddr; 71 | load_size = phdr_table_get_load_size(phdr_table, phdr_num, &min_vaddr); 72 | if (load_size == 0) { 73 | ELOG("\"%s\" has no loadable segments\n", filename); 74 | return false; 75 | } 76 | 77 | uint8_t* addr = reinterpret_cast(min_vaddr); 78 | // alloc map data, and load in addr 79 | void* start = new uint8_t[load_size]; 80 | 81 | load_start = start; 82 | load_bias = reinterpret_cast(start) - addr; 83 | return true; 84 | } 85 | 86 | /** 87 | * Map all loadable segments in process' address space. 88 | * This assume you already called reserveAddressSpace. 89 | */ 90 | bool ELFReader::loadSegments(){ 91 | for(int i=0;ip_type != PT_LOAD){ 94 | continue; 95 | } 96 | 97 | // Segment addresses in memory 98 | Elf_Addr seg_start = phdr->p_vaddr; 99 | Elf_Addr seg_end = seg_start + phdr->p_memsz; 100 | 101 | Elf_Addr seg_page_start = PAGE_START(seg_start); 102 | Elf_Addr seg_page_end = PAGE_END(seg_end); 103 | 104 | Elf_Addr seg_file_end = seg_start + phdr->p_filesz; 105 | 106 | // File offsets. 107 | Elf_Addr file_start = phdr->p_offset; 108 | Elf_Addr file_end = file_start + phdr->p_filesz; 109 | 110 | Elf_Addr file_page_start = PAGE_START(file_start); 111 | Elf_Addr file_length = file_end - file_page_start; 112 | 113 | if(file_length != 0){ 114 | // memory data loading 115 | void* load_point = (uint8_t*)seg_page_start + load_bias; 116 | if(!loadFileData(load_point, file_length, file_page_start)){ 117 | ELOG("couldn't map \"%s\" segment %d", filename, i); 118 | return false; 119 | } 120 | } 121 | 122 | // if the segment is writable, and does not end on a page boundary, 123 | // zero-fill it until the page limit. 124 | if((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0){ 125 | memset((uint8_t*)seg_file_end + load_bias, 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end)); 126 | } 127 | seg_file_end = PAGE_END(seg_file_end); 128 | 129 | // seg_file_end is now the first page address after the file 130 | // content. If seg_end is larger, we need to zero anything 131 | // between them. This is done by using a private anonymous 132 | // map for all extra pages. 133 | if(seg_page_end > seg_file_end){ 134 | void* load_point = (uint8_t*)load_bias + seg_file_end; 135 | memset(load_point, 0, seg_page_end - seg_file_end); 136 | } 137 | } 138 | return true; 139 | } 140 | 141 | /** 142 | * Returns the address of the program header table as it appears in the loaded 143 | * segments in memory. This is in contrast with 'phdr_table_' which 144 | * is temporary and will be released before the library is relocated. 145 | */ 146 | bool ELFReader::findPhdr() { 147 | const Elf_Phdr *phdr_limit = phdr_table + phdr_num; 148 | 149 | // If there is a PT_PHDR, use it directly 150 | for(const Elf_Phdr* phdr = phdr_table;phdr < phdr_limit;phdr++){ 151 | if(phdr->p_type == PT_PHDR){ 152 | return checkPhdr(load_bias + phdr->p_vaddr); 153 | } 154 | } 155 | 156 | // Otherwise, check the first loadable segment. If its file offset 157 | // is 0, it starts with the ELF header, and we can trivially find the 158 | // loaded program header from it. 159 | for(const Elf_Phdr* phdr = phdr_table; phdr < phdr_limit; phdr++){ 160 | if(phdr->p_type == PT_LOAD){ 161 | if(phdr->p_offset == 0){ 162 | Elf_Addr elf_addr = load_bias + phdr->p_vaddr; 163 | const Elf_Ehdr* ehdr = (const Elf_Ehdr*)(void *)elf_addr; 164 | Elf_Addr offset = ehdr->e_phoff; 165 | return checkPhdr((Elf_Addr)ehdr + offset); 166 | } 167 | break; 168 | } 169 | } 170 | ELOG("can't find loaded phdr for \"%s\"", filename); 171 | return false; 172 | } 173 | 174 | /** 175 | * Ensures that out program header is actually within a loadable 176 | * segment. This should help catch badly-formed ELF files that 177 | * would cause the linker to crash later when trying to access it. 178 | */ 179 | bool ELFReader::checkPhdr(Elf_Addr loaded){ 180 | const Elf_Phdr* phdr_limit = phdr_table + phdr_num; 181 | Elf_Addr loaded_end = loaded + (phdr_num * sizeof(Elf_Phdr)); 182 | for(Elf_Phdr* phdr = phdr_table; phdr < phdr_limit; phdr++){ 183 | if(phdr->p_type != PT_LOAD){ 184 | continue; 185 | } 186 | Elf_Addr seg_start = phdr->p_vaddr + load_bias; 187 | Elf_Addr seg_end = seg_start + phdr->p_filesz; 188 | if(seg_start <= loaded && loaded_end <= seg_end){ 189 | loaded_phdr = reinterpret_cast(loaded); 190 | return true; 191 | } 192 | } 193 | ELOG("\"%s\" loaded phdr %x not in loadable segment", filename, loaded); 194 | return false; 195 | } 196 | 197 | void ELFReader::damagePrint(){ 198 | switch(damageLevel){ 199 | case -1: 200 | LOG("Not verify yet."); break; 201 | case 0: 202 | LOG("\"%s\" is perfect. Do not need to be repaired.", filename); break; 203 | case 1: 204 | LOG("\"%s\" section invalid. But still have sh_size. Can use plan A to repair.", filename); break; 205 | case 2: 206 | LOG("\"%s\" section totally damage. Should use plan B to repair.", filename); break; 207 | case 3: 208 | LOG("\"%s\" is an invalid elf file. Cannot be run.", filename); break; 209 | } 210 | } 211 | 212 | bool ELFReader::readElfHeader(){ 213 | size_t sz = fread(&elf_header, sizeof(char), sizeof(elf_header), inputFile); 214 | 215 | if(sz < 0){ 216 | ELOG("Cannot read file \"%s\"", filename); 217 | return false; 218 | } 219 | if(sz != sizeof(elf_header)){ 220 | ELOG("\"%s\" is too small to be an ELF file.", filename); 221 | return false; 222 | } 223 | 224 | DLOG("Read ELF header success"); 225 | return true; 226 | } 227 | 228 | /* Assume that elf header have been read successful. */ 229 | bool ELFReader::verifyElfHeader(){ 230 | 231 | if(!elf_header.checkMagic()){ // using the function elf.h support 232 | ELOG("\"%s\" has bad elf magic number. May not an elf file", filename); 233 | return false; 234 | } 235 | 236 | if(elf_header.getFileClass() == ELFCLASS64){ 237 | ELOG("Not support 64-bit so repair temporary."); 238 | return false; 239 | } 240 | 241 | if(elf_header.getFileClass() != ELFCLASS32){ 242 | ELOG("\"%s\" is not a 32-bit file", filename); 243 | return false; 244 | } 245 | VLOG("32-bit file \"%s\" read.", filename); 246 | 247 | if(elf_header.getDataEncoding() != ELFDATA2LSB){ 248 | ELOG("\"%s\" not little-endian. Unsupport.", filename); 249 | return false; 250 | } 251 | 252 | if(elf_header.e_type != ET_DYN){ 253 | ELOG("\"%s\" has unexpected e_type. Not a .so file", filename); 254 | return false; 255 | } 256 | 257 | if(elf_header.e_version != EV_CURRENT){ 258 | ELOG("\"%s\" has unexpected e_version", filename); 259 | return false; 260 | } 261 | 262 | DLOG("ELF header verify pass."); 263 | return true; 264 | } 265 | 266 | 267 | bool ELFReader::readProgramHeader(){ 268 | phdr_num = elf_header.e_phnum; 269 | phdr_entrySize = elf_header.e_phentsize; 270 | 271 | // phdr table max size is 65536, then we can calculate the max of phdr_num 272 | if(phdr_num < 1 || phdr_num > 65536/sizeof(Elf_Phdr)){ 273 | ELOG("\"%s\" has invalid program header number", filename); 274 | return false; 275 | } 276 | 277 | phdr_size = phdr_num * phdr_entrySize; 278 | void *mapPhdr = new uint8_t[phdr_size]; 279 | if(!loadFileData(mapPhdr, phdr_size, elf_header.e_phoff)){ 280 | ELOG("\"%s\" has not valid program header data.", filename); 281 | return false; 282 | } 283 | phdr_table = reinterpret_cast(mapPhdr); 284 | 285 | DLOG("Read program header success."); 286 | return true; 287 | } 288 | 289 | bool ELFReader::readSectionHeader(){ 290 | if(elf_header.e_shnum < 1){ 291 | // Because program valid is necessary. So we use ELOG print the error message. 292 | // But section need to be repaired. So we accept it invalid. 293 | // We use VLOG for that who want verbose information. 294 | VLOG("\"%s\" don't have valid section num.", filename); 295 | return false; 296 | } 297 | shdr_num = elf_header.e_shnum; 298 | shdr_entrySize = elf_header.e_shentsize; 299 | 300 | // section header table should behind the program header table 301 | if(elf_header.e_shoff < elf_header.e_phoff + phdr_entrySize*phdr_num){ 302 | VLOG("\"%s\" don't have valid section offset", filename); 303 | return false; 304 | } 305 | 306 | shdr_size = shdr_num * shdr_entrySize; 307 | void *mapShdr = new uint8_t[shdr_size]; 308 | if(!loadFileData(mapShdr, shdr_size, elf_header.e_shoff)){ 309 | VLOG("\"%s\" don't have valid section data.", filename); 310 | return false; 311 | } 312 | shdr_table = reinterpret_cast(mapShdr); 313 | 314 | DLOG("Read section header success."); 315 | return true; 316 | } 317 | 318 | 319 | /** 320 | * Only call after read section header success. 321 | * Just for build the new file. 322 | * So we can assume that program header and section header valid here. 323 | */ 324 | bool ELFReader::readOtherPart(){ 325 | midPart_start = elf_header.e_phoff + phdr_num*phdr_entrySize; 326 | midPart_end = elf_header.e_shoff; 327 | midPart_size = midPart_end - midPart_start; 328 | midPart = new uint8_t[midPart_size]; 329 | 330 | if(!loadFileData(midPart, midPart_size, midPart_start)){ 331 | ELOG("\"%s\" don't have valid data.", filename); 332 | return false; 333 | } 334 | 335 | DLOG("Read the other part data success."); 336 | return true; 337 | } 338 | 339 | /** 340 | * Just verify the status of section header. 341 | * Do not try to repair it. 342 | */ 343 | bool ELFReader::checkSectionHeader(){ 344 | //check SHN_UNDEF section 345 | Elf_Shdr temp; 346 | memset((void *)&temp, 0, sizeof(Elf_Shdr)); 347 | if(memcmp(shdr_table, &temp, sizeof(Elf_Shdr))){ 348 | VLOG("Wrong section data in 0 section header."); 349 | damageLevel = 2; 350 | return false; 351 | } 352 | 353 | // Get the two load segment index at phdr_table. 354 | // Thus wo can use segment load address and offset 355 | // to check the section header. 356 | int loadIndex[2] = {-1, -1}; 357 | for(int i=0, j=0;i= phdr_table[loadIndex[0]].p_filesz) { break; } 399 | 400 | if(curAddr != shdr_table[i].sh_addr || curOffset != shdr_table[i].sh_offset){ 401 | VLOG("Not valid section address or offset at section index %d", i); 402 | isShdrValid = false; 403 | } 404 | 405 | } 406 | } 407 | 408 | // check the second LOAD segment 409 | // if section and offset invalid. All shdr_size would been check in previous loop 410 | // This loop will pass 411 | if(isShdrValid){ 412 | // Because we have already check sh_size in previous loop. 413 | // We don't need to check again with this section. 414 | if(shdr_table[i].sh_addr != phdr_table[loadIndex[1]].p_paddr || 415 | shdr_table[i].sh_offset != phdr_table[loadIndex[1]].p_offset){ 416 | VLOG("Not valid section address or offset at section index %d", i); 417 | isShdrValid = false; 418 | } 419 | i++; 420 | } 421 | if(i < shdr_num) DLOG("Check the section mapping at second LOAD segment."); 422 | for(;i= phdr_table[loadIndex[1]].p_filesz + phdr_table[loadIndex[1]].p_offset) { break; } 443 | 444 | if(curAddr != shdr_table[i].sh_addr || curOffset != shdr_table[i].sh_offset){ 445 | VLOG("Not valid section address or offset at section index %d", i); 446 | isShdrValid = false; 447 | } 448 | } 449 | } 450 | 451 | //FIXME: then figure with .comment .shstrtab and others don't load 452 | // it's unimportant for these section. Temporary not handle it. 453 | if(isShdrValid){ 454 | VLOG("The section headers are valid."); 455 | damageLevel = 0; 456 | } else{ 457 | VLOG("Section headers need a bit repair"); 458 | damageLevel = 1; 459 | } 460 | DLOG("Finish section check. Not fully damage."); 461 | return isShdrValid; 462 | } 463 | 464 | bool ELFReader::loadFileData(void *addr, size_t len, int offset){ 465 | fseek(inputFile, offset, SEEK_SET); 466 | size_t sz = fread(addr, sizeof(uint8_t), len, inputFile); 467 | 468 | if(sz < 0){ 469 | ELOG("\"%s\" file read error", filename); 470 | return false; 471 | } 472 | 473 | if(sz != len){ 474 | ELOG("\"%s\" has no enough data at %x:%x, not valid file.", filename, offset, len); 475 | return false; 476 | } 477 | return true; 478 | 479 | } 480 | 481 | 482 | /* Returns the size of the extent of all the possibly non-contiguous 483 | * loadable segments in an ELF program header table. This corresponds 484 | * to the page-aligned size in bytes that needs to be reserved in the 485 | * process' address space. If there are no loadable segments, 0 is 486 | * returned. 487 | * 488 | * If out_min_vaddr or out_max_vaddr are non-NULL, they will be 489 | * set to the minimum and maximum addresses of pages to be reserved, 490 | * or 0 if there is nothing to load. 491 | */ 492 | size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, 493 | size_t phdr_count, 494 | Elf_Addr* out_min_vaddr, 495 | Elf_Addr* out_max_vaddr, 496 | Elf_Addr* out_max_endAddr) 497 | { 498 | Elf_Addr min_vaddr = 0xFFFFFFFFU; 499 | Elf_Addr max_vaddr = 0x00000000U; 500 | 501 | bool found_pt_load = false; 502 | for (size_t i = 0; i < phdr_count; ++i) { 503 | const Elf_Phdr* phdr = &phdr_table[i]; 504 | 505 | if (phdr->p_type != PT_LOAD) { 506 | continue; 507 | } 508 | found_pt_load = true; 509 | 510 | if (phdr->p_vaddr < min_vaddr) { 511 | min_vaddr = phdr->p_vaddr; 512 | } 513 | 514 | if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { 515 | max_vaddr = phdr->p_vaddr + phdr->p_memsz; 516 | } 517 | } 518 | if (!found_pt_load) { 519 | min_vaddr = 0x00000000U; 520 | } 521 | 522 | // Add by giglf. We need to record the end of the segment. 523 | // Not the end of the page. Thus we can use the end address 524 | // to append the .bss section and record the end of the .data. 525 | if(out_max_endAddr != NULL){ 526 | *out_max_endAddr = max_vaddr; 527 | } 528 | 529 | min_vaddr = PAGE_START(min_vaddr); 530 | max_vaddr = PAGE_END(max_vaddr); 531 | 532 | if (out_min_vaddr != NULL) { 533 | *out_min_vaddr = min_vaddr; 534 | } 535 | if (out_max_vaddr != NULL) { 536 | *out_max_vaddr = max_vaddr; 537 | } 538 | return max_vaddr - min_vaddr; 539 | } 540 | 541 | /* Return the address and size of the ELF file's .dynamic section in memory, 542 | * or NULL if missing. 543 | * 544 | * Input: 545 | * phdr_table -> program header table 546 | * phdr_count -> number of entries in tables 547 | * load_bias -> load bias 548 | * Output: 549 | * dynamic -> address of table in memory (NULL on failure). 550 | * dynamic_count -> number of items in table (0 on failure). 551 | * dynamic_flags -> protection flags for section (unset on failure) 552 | * Return: 553 | * void 554 | */ 555 | void 556 | phdr_table_get_dynamic_section(const Elf_Phdr* phdr_table, 557 | int phdr_count, 558 | Elf_Addr load_bias, 559 | Elf_Dyn** dynamic, 560 | size_t* dynamic_count, 561 | Elf_Word* dynamic_flags) 562 | { 563 | const Elf_Phdr* phdr = phdr_table; 564 | const Elf_Phdr* phdr_limit = phdr + phdr_count; 565 | 566 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 567 | if (phdr->p_type != PT_DYNAMIC) { 568 | continue; 569 | } 570 | 571 | *dynamic = reinterpret_cast(load_bias + phdr->p_vaddr); 572 | if (dynamic_count) { 573 | *dynamic_count = (unsigned)(phdr->p_memsz / sizeof(Elf_Dyn)); 574 | } 575 | if (dynamic_flags) { 576 | *dynamic_flags = phdr->p_flags; 577 | } 578 | return; 579 | } 580 | *dynamic = NULL; 581 | if (dynamic_count) { 582 | *dynamic_count = 0; 583 | } 584 | } 585 | 586 | 587 | /* Return the address and size of the .ARM.exidx section in memory, 588 | * if present. 589 | * 590 | * Input: 591 | * phdr_table -> program header table 592 | * phdr_count -> number of entries in tables 593 | * load_bias -> load bias 594 | * Output: 595 | * arm_exidx -> address of table in memory (NULL on failure). 596 | * arm_exidx_count -> number of items in table (0 on failure). 597 | * Return: 598 | * 0 on error, -1 on failure (_no_ error code in errno) 599 | */ 600 | int 601 | phdr_table_get_arm_exidx(const Elf_Phdr* phdr_table, 602 | int phdr_count, 603 | Elf_Addr load_bias, 604 | Elf_Addr** arm_exidx, 605 | unsigned* arm_exidx_count) 606 | { 607 | const Elf_Phdr* phdr = phdr_table; 608 | const Elf_Phdr* phdr_limit = phdr + phdr_count; 609 | 610 | for (phdr = phdr_table; phdr < phdr_limit; phdr++) { 611 | if (phdr->p_type != PT_ARM_EXIDX) 612 | continue; 613 | 614 | *arm_exidx = (Elf_Addr*)(load_bias + phdr->p_vaddr); 615 | *arm_exidx_count = (unsigned)(phdr->p_memsz / sizeof(Elf_Addr)); 616 | return 0; 617 | } 618 | *arm_exidx = NULL; 619 | *arm_exidx_count = 0; 620 | return -1; 621 | } 622 | 623 | 624 | // get the interp section address 625 | void phdr_table_get_interpt_section(const Elf_Phdr* phdr_table, 626 | int phdr_count, 627 | Elf_Addr load_bias, 628 | Elf_Addr** interp, 629 | size_t* interp_size) 630 | { 631 | const Elf_Phdr* phdr = phdr_table; 632 | const Elf_Phdr* phdr_limit = phdr + phdr_count; 633 | 634 | for(phdr = phdr_table; phdr < phdr_limit; phdr++){ 635 | if(phdr->p_type != PT_INTERP) 636 | continue; 637 | 638 | *interp = (Elf_Addr*)(load_bias + phdr->p_vaddr); 639 | *interp_size = phdr->p_filesz; 640 | return; 641 | } 642 | *interp = NULL; 643 | } -------------------------------------------------------------------------------- /src/ELFReader.h: -------------------------------------------------------------------------------- 1 | #ifndef _SO_REBUILDER_ELFREADER_H_ 2 | #define _SO_REBUILDER_ELFREADER_H_ 3 | 4 | #include 5 | #include "elf.h" 6 | #include "exutil.h" 7 | 8 | class ELFReader{ 9 | 10 | public: 11 | ELFReader(const char * filename); 12 | ~ELFReader(); 13 | 14 | bool load(); 15 | bool read(); 16 | void damagePrint(); 17 | 18 | private: 19 | 20 | bool readElfHeader(); 21 | bool verifyElfHeader(); 22 | bool readProgramHeader(); 23 | bool readSectionHeader(); 24 | bool readOtherPart(); 25 | bool reserveAddressSpace(); 26 | bool loadSegments(); 27 | bool findPhdr(); 28 | bool checkPhdr(Elf_Addr loaded); 29 | 30 | bool checkSectionHeader(); 31 | bool loadFileData(void *addr, size_t len, int offset); 32 | 33 | const char* filename; 34 | FILE* inputFile; 35 | 36 | bool didLoad; 37 | bool didRead; 38 | /** 39 | * This is a parameter define by myself, which target at 40 | * evaluate the damage level of the .so file. 41 | * I have made 4 number to represent it. The bigger number 42 | * stand for bigger damage of the .so file. 43 | * -1 ==> The file haven't evaluated yet. 44 | * 0 ==> The so file is complete. 45 | * 1 ==> Offset and Vaddr in section header have been 46 | * damaged. But still have size information. 47 | * 2 ==> All section information have been damaged. 48 | * 3 ==> The whole file beyond recognition. 49 | * The .so file still can be used in damage level 0~2. But 50 | * cannot run under the level 3. The ELFRebuilder will give 51 | * different programs to repair the file according to the 52 | * damage level. 53 | */ 54 | int damageLevel; 55 | 56 | 57 | /** 58 | * This is standard structure for an elf file. If damageLevel is 1 or 0. 59 | * We don't necessary load the content into memory and try to rebuild the 60 | * section. 61 | * Otherwise, we need to load the so file and rebuild the section. 62 | */ 63 | Elf_Ehdr elf_header; // store elf header 64 | 65 | Elf_Phdr* phdr_table; // store program header table 66 | Elf_Half phdr_entrySize; // program header entry size 67 | size_t phdr_num; // the number of program header 68 | size_t phdr_size; // size of program headers 69 | 70 | void *midPart; // the load address of the middle part between program table and section table 71 | Elf_Addr midPart_start; // start address between program table and section table 72 | Elf_Addr midPart_end; // end address between program table and section table 73 | size_t midPart_size; // size of the Middle part. 74 | 75 | Elf_Shdr* shdr_table; // store section header table 76 | Elf_Half shdr_entrySize; // section header entry size 77 | size_t shdr_num; // the number of section header 78 | size_t shdr_size; // size of section headers 79 | 80 | /* Load information */ 81 | void* load_start; // First page of reserved address space. 82 | Elf_Addr load_size; // Size in bytes of reserved address space. 83 | Elf_Addr load_bias; // Load bias. 84 | 85 | const Elf_Phdr* loaded_phdr; // Loaded phdr. 86 | 87 | public: 88 | 89 | bool isRead() { return didRead; } 90 | bool isLoad() { return didLoad; } 91 | int getDamageLevel() { return damageLevel; } 92 | const char* getFileName() { return filename; } 93 | 94 | Elf_Ehdr getElfHeader() { return elf_header; } 95 | Elf_Shdr* getShdrTable() { return shdr_table; } 96 | void* getMidPart() { return midPart; } 97 | Elf_Phdr* getPhdrTable() { return phdr_table; } 98 | 99 | size_t getPhdrSize() { return phdr_size; } 100 | size_t getMidPartSize() { return midPart_size; } 101 | size_t getShdrSize() { return shdr_size; } 102 | 103 | int getShdrNum() { return shdr_num; } 104 | int getPhdrNum() { return phdr_num; } 105 | 106 | const Elf_Phdr* getLoadedPhdr() { return loaded_phdr; } 107 | Elf_Addr getLoadBias() { return load_bias; } 108 | 109 | void setDumpSoFile(bool dump) { dump_so_file = dump; } 110 | void setDumpSoBase(Elf_Addr base){ dump_so_base = base; } 111 | bool isDumpSoFile() { return dump_so_file; } 112 | Elf_Addr getDumpSoBase() { return dump_so_base; } 113 | private: 114 | bool dump_so_file = false; 115 | Elf_Addr dump_so_base = 0; 116 | 117 | }; 118 | 119 | 120 | //The functions below are refer to android source 121 | size_t phdr_table_get_load_size(const Elf_Phdr* phdr_table, 122 | size_t phdr_count, 123 | Elf_Addr* out_min_vaddr = NULL, 124 | Elf_Addr* out_max_vaddr = NULL, 125 | Elf_Addr* out_max_endAddress = NULL); 126 | 127 | void phdr_table_get_dynamic_section(const Elf_Phdr* phdr_table, 128 | int phdr_count, 129 | Elf_Addr load_bias, 130 | Elf_Dyn** dynamic, 131 | size_t* dynamic_count, 132 | Elf_Word* dynamic_flags); 133 | 134 | int phdr_table_get_arm_exidx(const Elf_Phdr* phdr_table, 135 | int phdr_count, 136 | Elf_Addr load_bias, 137 | Elf_Addr** arm_exidx, 138 | unsigned* arm_exidix_count); 139 | 140 | void phdr_table_get_interpt_section(const Elf_Phdr* phdr_table, 141 | int phdr_count, 142 | Elf_Addr load_bias, 143 | Elf_Addr** interp, 144 | size_t* interp_size); 145 | 146 | 147 | #endif -------------------------------------------------------------------------------- /src/ELFRebuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "exutil.h" 2 | #include "ELFRebuilder.h" 3 | #include "Log.h" 4 | #include 5 | 6 | ELFRebuilder::ELFRebuilder(ELFReader &_reader, bool _force) 7 | : reader(_reader), force(_force){ 8 | 9 | elf_header = reader.getElfHeader(); 10 | phdr_table = reader.getPhdrTable(); 11 | 12 | } 13 | 14 | ELFRebuilder::~ELFRebuilder(){ 15 | if(rebuild_data != NULL){ 16 | delete [](uint8_t*)rebuild_data; 17 | } 18 | } 19 | 20 | 21 | bool ELFRebuilder::rebuild(){ 22 | if(force || reader.getDamageLevel() == 2){ 23 | if(!reader.isLoad()) reader.load(); 24 | return totalRebuild(); 25 | } else if(reader.getDamageLevel() == 1){ 26 | return simpleRebuild() && rebuildData(); 27 | } 28 | return false; 29 | } 30 | 31 | 32 | /** 33 | * Just repair the section headers address and offset. 34 | * This function is just like the checkSectionHeader in ELFReader. 35 | * Calling this function. We assume that the so-file have valid 36 | * program header, elf header, and valid size of each section. 37 | * The all thing that this file need is section offset and address. 38 | */ 39 | bool ELFRebuilder::simpleRebuild(){ 40 | VLOG("Starting repair the section."); 41 | rebuild_size = sizeof(Elf_Ehdr) + reader.getPhdrSize() + reader.getMidPartSize() + reader.getShdrSize(); 42 | Elf_Shdr *shdr_table = reader.getShdrTable(); 43 | Elf_Phdr *phdr_table = reader.getPhdrTable(); 44 | int shdr_num = reader.getShdrNum(); 45 | int phdr_num = reader.getPhdrNum(); 46 | 47 | int loadIndex[2] = {-1, -1}; 48 | for(int i=0, j=0;i= phdr_table[loadIndex[0]].p_filesz + phdr_table[loadIndex[0]].p_offset) { break; } 70 | shdr_table[i].sh_addr = curAddr; 71 | shdr_table[i].sh_offset = curOffset; 72 | 73 | } 74 | 75 | // Rebuild the second LOAD segment 76 | // First get the second LOAD segment address and offset 77 | DLOG("Start repair the section mapping at second LOAD segment."); 78 | shdr_table[i].sh_addr = phdr_table[loadIndex[1]].p_vaddr; 79 | shdr_table[i].sh_offset = phdr_table[loadIndex[1]].p_offset; 80 | 81 | for(i=i+1;i= phdr_table[loadIndex[1]].p_filesz + phdr_table[loadIndex[1]].p_offset) { break; } 103 | } 104 | 105 | // The remain section won't be load. So the address is 0. 106 | // And the .bss section type is SHT_NOBITS. 107 | // So the follow section offset is the same as it. 108 | DLOG("Repair the not LOAD section."); 109 | i++; 110 | shdr_table[i].sh_addr = 0; 111 | shdr_table[i].sh_offset = shdr_table[i-1].sh_offset; 112 | for(i=i+1;i(reader.getMidPart()); 138 | DLOG("Copy midPart data. MidPart size = %d", midPart_size); 139 | memcpy(tmp, midPart, midPart_size); 140 | tmp += midPart_size; 141 | 142 | size_t shdr_size = reader.getShdrSize(); 143 | DLOG("Copy section header data. Section header size = %d", shdr_size); 144 | memcpy(tmp, reader.getShdrTable(), shdr_size); 145 | 146 | DLOG("rebuild_data prepared."); 147 | return false; 148 | } 149 | 150 | bool ELFRebuilder::totalRebuild(){ 151 | VLOG("Using plan B to rebuild the section."); 152 | if(rebuildPhdr() && readSoInfo() && rebuildShdr() && rebuildRelocs() && rebuildFinish()){ 153 | return true; 154 | } 155 | ELOG("Using plan B to rebuild failed."); 156 | exit(EXIT_FAILURE); 157 | } 158 | 159 | /** 160 | * Expend file size to memory size. Because we will dump them 161 | * all from memory. After rebuild, the load size of the file 162 | * is exactly the memory size. We don't need to padding for the 163 | * page align. Because the data of the file is already align with 164 | * page. 165 | */ 166 | bool ELFRebuilder::rebuildPhdr(){ 167 | Elf_Phdr* phdr = (Elf_Phdr *)reader.getLoadedPhdr(); 168 | for(int i=0;id_tag != DT_NULL;dyn++){ 202 | switch(dyn->d_tag){ 203 | case DT_HASH: 204 | si.hash = dyn->d_un.d_ptr + base; 205 | si.nbucket = ((unsigned *)si.hash)[0]; 206 | si.nchain = ((unsigned *)si.hash)[1]; 207 | si.bucket = (unsigned *)si.hash + 8; 208 | si.chain = (unsigned *)si.bucket + 4*si.nbucket; 209 | break; 210 | case DT_STRTAB: 211 | si.strtab = (const char*)(dyn->d_un.d_ptr + base); 212 | VLOG("string table found at %x", dyn->d_un.d_ptr); 213 | break; 214 | case DT_SYMTAB: 215 | si.symtab = (Elf_Sym *) (dyn->d_un.d_ptr + base); 216 | VLOG("symbol table found at %x", dyn->d_un.d_ptr); 217 | break; 218 | case DT_PLTREL: 219 | if (dyn->d_un.d_val != DT_REL) { 220 | VLOG("unsupported DT_RELA in \"%s\"", si.name); 221 | return false; 222 | } 223 | break; 224 | case DT_JMPREL: 225 | si.plt_rel = (Elf_Rel*) (dyn->d_un.d_ptr + base); 226 | VLOG("%s plt_rel (DT_JMPREL) found at %x", si.name, dyn->d_un.d_ptr); 227 | break; 228 | case DT_PLTRELSZ: 229 | si.plt_rel_count = dyn->d_un.d_val / sizeof(Elf_Rel); 230 | VLOG("%s plt_rel_count (DT_PLTRELSZ) %d", si.name, si.plt_rel_count); 231 | break; 232 | case DT_REL: 233 | si.rel = (Elf_Rel*) (dyn->d_un.d_ptr + base); 234 | VLOG("%s rel (DT_REL) found at %x", si.name, dyn->d_un.d_ptr); 235 | break; 236 | case DT_RELSZ: 237 | si.rel_count = dyn->d_un.d_val / sizeof(Elf_Rel); 238 | VLOG("%s rel_size (DT_RELSZ) %d", si.name, si.rel_count); 239 | break; 240 | case DT_PLTGOT: 241 | /* Save this in case we decide to do lazy binding. We don't yet. */ 242 | si.plt_got = (Elf_Addr *)(dyn->d_un.d_ptr + base); 243 | break; 244 | case DT_DEBUG: 245 | // Set the DT_DEBUG entry to the address of _r_debug for GDB 246 | // if the dynamic table is writable 247 | break; 248 | case DT_RELA: 249 | VLOG("unsupported DT_RELA in \"%s\"", si.name); 250 | return false; 251 | case DT_INIT: 252 | si.init_func = reinterpret_cast(dyn->d_un.d_ptr + base); 253 | VLOG("%s constructors (DT_INIT) found at %x", si.name, dyn->d_un.d_ptr); 254 | break; 255 | case DT_FINI: 256 | si.fini_func = reinterpret_cast(dyn->d_un.d_ptr + base); 257 | VLOG("%s destructors (DT_FINI) found at %x", si.name, dyn->d_un.d_ptr); 258 | break; 259 | case DT_INIT_ARRAY: 260 | si.init_array = reinterpret_cast(dyn->d_un.d_ptr + base); 261 | VLOG("%s constructors (DT_INIT_ARRAY) found at %x", si.name, dyn->d_un.d_ptr); 262 | break; 263 | case DT_INIT_ARRAYSZ: 264 | si.init_array_count = ((unsigned)dyn->d_un.d_val) / sizeof(Elf_Addr); 265 | VLOG("%s constructors (DT_INIT_ARRAYSZ) %d", si.name, si.init_array_count); 266 | break; 267 | case DT_FINI_ARRAY: 268 | si.fini_array = reinterpret_cast(dyn->d_un.d_ptr + base); 269 | VLOG("%s destructors (DT_FINI_ARRAY) found at %x", si.name, dyn->d_un.d_ptr); 270 | break; 271 | case DT_FINI_ARRAYSZ: 272 | si.fini_array_count = ((unsigned)dyn->d_un.d_val) / sizeof(Elf_Addr); 273 | VLOG("%s destructors (DT_FINI_ARRAYSZ) %d", si.name, si.fini_array_count); 274 | break; 275 | case DT_PREINIT_ARRAY: 276 | si.preinit_array = reinterpret_cast(dyn->d_un.d_ptr + base); 277 | VLOG("%s constructors (DT_PREINIT_ARRAY) found at %d", si.name, dyn->d_un.d_ptr); 278 | break; 279 | case DT_PREINIT_ARRAYSZ: 280 | si.preinit_array_count = ((unsigned)dyn->d_un.d_val) / sizeof(Elf_Addr); 281 | VLOG("%s constructors (DT_PREINIT_ARRAYSZ) %d", si.name,si.preinit_array_count); 282 | break; 283 | case DT_TEXTREL: 284 | si.has_text_relocations = true; 285 | break; 286 | case DT_SYMBOLIC: 287 | si.has_DT_SYMBOLIC = true; 288 | break; 289 | case DT_NEEDED: 290 | ++needed_count; 291 | break; 292 | case DT_FLAGS: 293 | if (dyn->d_un.d_val & DF_TEXTREL) { 294 | si.has_text_relocations = true; 295 | } 296 | if (dyn->d_un.d_val & DF_SYMBOLIC) { 297 | si.has_DT_SYMBOLIC = true; 298 | } 299 | break; 300 | case DT_STRSZ: 301 | si.strtabsize = dyn->d_un.d_val; 302 | break; 303 | case DT_SYMENT: 304 | si.dynsym_size = dyn->d_un.d_val; 305 | break; 306 | case DT_RELENT: 307 | break; 308 | case DT_MIPS_RLD_MAP: 309 | // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB. 310 | break; 311 | case DT_MIPS_RLD_VERSION: 312 | case DT_MIPS_FLAGS: 313 | case DT_MIPS_BASE_ADDRESS: 314 | case DT_MIPS_UNREFEXTNO: 315 | break; 316 | 317 | case DT_MIPS_SYMTABNO: 318 | si.mips_symtabno = dyn->d_un.d_val; 319 | break; 320 | 321 | case DT_MIPS_LOCAL_GOTNO: 322 | si.mips_local_gotno = dyn->d_un.d_val; 323 | break; 324 | 325 | case DT_MIPS_GOTSYM: 326 | si.mips_gotsym = dyn->d_un.d_val; 327 | break; 328 | case DT_SONAME: 329 | si.name = (const char *) (dyn->d_un.d_ptr + base); 330 | VLOG("soname %s", si.name); 331 | break; 332 | default: 333 | VLOG("Unused DT entry: type 0x%08x arg 0x%08x", dyn->d_tag, dyn->d_un.d_val); 334 | break; 335 | } 336 | } 337 | DLOG("Dynamic read finish."); 338 | return true; 339 | } 340 | 341 | bool ELFRebuilder::rebuildShdr(){ 342 | shstrtab.clear(); 343 | shdrs.clear(); 344 | Elf_Addr base = si.load_bias; 345 | 346 | Elf_Shdr shdr; 347 | memset((void*)&shdr, 0, sizeof(shdr)); 348 | shstrtab.push_back('\0'); 349 | shdrs.push_back(shdr); 350 | 351 | // generate .interp 352 | if(si.interp != nullptr){ 353 | memset((void*)&shdr, 0, sizeof(shdr)); 354 | sINTERP = shdrs.size(); 355 | shdr.sh_name = shstrtab.length(); 356 | shstrtab.append(".interp"); 357 | shstrtab.push_back('\0'); 358 | 359 | shdr.sh_type = SHT_PROGBITS; 360 | shdr.sh_flags = SHF_ALLOC; 361 | shdr.sh_addr = (Elf_Addr)si.interp - base; 362 | shdr.sh_offset = shdr.sh_addr; 363 | shdr.sh_size = si.interp_size; 364 | shdr.sh_link = 0; 365 | shdr.sh_info = 0; 366 | shdr.sh_addralign = 1; 367 | shdr.sh_entsize = 0; 368 | 369 | shdrs.push_back(shdr); 370 | } 371 | 372 | //generate .dynsym 373 | if(si.symtab != nullptr){ 374 | memset((void*)&shdr, 0, sizeof(shdr)); 375 | sDYNSYM = shdrs.size(); 376 | shdr.sh_name = shstrtab.length(); 377 | shstrtab.append(".dynsym"); 378 | shstrtab.push_back('\0'); 379 | 380 | shdr.sh_type = SHT_DYNSYM; 381 | shdr.sh_flags = SHF_ALLOC; 382 | shdr.sh_addr = (Elf_Addr)si.symtab - base; 383 | shdr.sh_offset = shdr.sh_addr; 384 | shdr.sh_size = si.dynsym_size; 385 | shdr.sh_link = 0; // link to dynstr later 386 | shdr.sh_info = 1; 387 | shdr.sh_addralign = 4; 388 | shdr.sh_entsize = 0x10; 389 | 390 | shdrs.push_back(shdr); 391 | } 392 | 393 | //generate .dynstr 394 | if(si.strtab != nullptr){ 395 | memset((void*)&shdr, 0, sizeof(shdr)); 396 | sDYNSTR = shdrs.size(); 397 | shdr.sh_name = shstrtab.length(); 398 | shstrtab.append(".dynstr"); 399 | shstrtab.push_back('\0'); 400 | 401 | shdr.sh_type = SHT_STRTAB; 402 | shdr.sh_flags = SHF_ALLOC; 403 | shdr.sh_addr = (Elf_Addr)si.strtab - base; 404 | shdr.sh_offset = shdr.sh_addr; 405 | shdr.sh_size = si.strtabsize; 406 | shdr.sh_link = 0; 407 | shdr.sh_info = 0; 408 | shdr.sh_addralign = 1; 409 | shdr.sh_entsize = 0; 410 | 411 | shdrs.push_back(shdr); 412 | } 413 | 414 | //generate .hash 415 | if(si.hash != 0){ 416 | memset((void*)&shdr, 0, sizeof(shdr)); 417 | sHASH = shdrs.size(); 418 | shdr.sh_name = shstrtab.length(); 419 | shstrtab.append(".hash"); 420 | shstrtab.push_back('\0'); 421 | 422 | shdr.sh_type = SHT_HASH; 423 | shdr.sh_flags = SHF_ALLOC; 424 | shdr.sh_addr = si.hash - base; 425 | shdr.sh_offset = shdr.sh_addr; 426 | shdr.sh_size = (si.nbucket + si.nchain + 2) * sizeof(Elf_Addr); 427 | shdr.sh_link = sDYNSYM; 428 | shdr.sh_info = 0; 429 | shdr.sh_addralign = 4; 430 | shdr.sh_entsize = 4; 431 | 432 | shdrs.push_back(shdr); 433 | } 434 | 435 | //generate .rel.dyn 436 | if(si.rel != nullptr){ 437 | memset((void*)&shdr, 0, sizeof(shdr)); 438 | sRELDYN = shdrs.size(); 439 | shdr.sh_name = shstrtab.length(); 440 | shstrtab.append(".rel.dyn"); 441 | shstrtab.push_back('\0'); 442 | 443 | shdr.sh_type = SHT_REL; 444 | shdr.sh_flags = SHF_ALLOC; 445 | shdr.sh_addr = (Elf_Addr)si.rel - base; 446 | shdr.sh_offset = shdr.sh_addr; 447 | shdr.sh_size = si.rel_count * sizeof(Elf_Rel); 448 | shdr.sh_link = sDYNSYM; 449 | shdr.sh_info = 0; 450 | shdr.sh_addralign = 4; 451 | shdr.sh_entsize = 8; 452 | 453 | shdrs.push_back(shdr); 454 | } 455 | 456 | //generate .rel.plt 457 | if(si.plt_rel != nullptr){ 458 | memset((void*)&shdr, 0, sizeof(shdr)); 459 | sRELPLT = shdrs.size(); 460 | shdr.sh_name = shstrtab.length(); 461 | shstrtab.append(".rel.plt"); 462 | shstrtab.push_back('\0'); 463 | 464 | shdr.sh_type = SHT_REL; 465 | shdr.sh_flags = SHF_ALLOC; 466 | shdr.sh_addr = (Elf_Addr)si.plt_rel - base; 467 | shdr.sh_offset = shdr.sh_addr; 468 | shdr.sh_size = si.plt_rel_count * sizeof(Elf_Rel); 469 | shdr.sh_link = sDYNSYM; 470 | shdr.sh_info = 0; 471 | shdr.sh_addralign = 4; 472 | shdr.sh_entsize = 8; 473 | 474 | shdrs.push_back(shdr); 475 | } 476 | 477 | //generate .plt with .rel.plt 478 | if(si.plt_rel != nullptr){ 479 | memset((void*)&shdr, 0, sizeof(shdr)); 480 | sPLT = shdrs.size(); 481 | shdr.sh_name = shstrtab.length(); 482 | shstrtab.append(".plt"); 483 | shstrtab.push_back('\0'); 484 | 485 | shdr.sh_type = SHT_PROGBITS; 486 | shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 487 | shdr.sh_addr = shdrs[sRELPLT].sh_addr + shdrs[sRELPLT].sh_size; 488 | shdr.sh_offset = shdr.sh_addr; 489 | shdr.sh_size = 20 + 12 * shdrs[sRELPLT].sh_size/sizeof(Elf_Rel); 490 | shdr.sh_link = 0; 491 | shdr.sh_info = 0; 492 | shdr.sh_addralign = 4; 493 | shdr.sh_entsize = 0; 494 | 495 | shdrs.push_back(shdr); 496 | } 497 | 498 | //generate .text&.ARM.extab 499 | if(si.plt_rel != nullptr){ 500 | memset((void*)&shdr, 0, sizeof(shdr)); 501 | sTEXTTAB = shdrs.size(); 502 | Elf_Word sLAST = sTEXTTAB - 1; 503 | shdr.sh_name = shstrtab.length(); 504 | shstrtab.append(".text&.ARM.extab"); 505 | shstrtab.push_back('\0'); 506 | 507 | shdr.sh_type = SHT_PROGBITS; 508 | shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 509 | shdr.sh_addr = shdrs[sLAST].sh_addr + shdrs[sLAST].sh_size; 510 | shdr.sh_offset = shdr.sh_addr; 511 | shdr.sh_size = 0; //TODO: calculate later 512 | shdr.sh_link = 0; 513 | shdr.sh_info = 0; 514 | shdr.sh_addralign = 8; 515 | shdr.sh_entsize = 0; 516 | 517 | shdrs.push_back(shdr); 518 | } 519 | 520 | //generate .ARM.exidx 521 | if(si.ARM_exidx != nullptr){ 522 | memset((void*)&shdr, 0, sizeof(shdr)); 523 | sARMEXIDX = shdrs.size(); 524 | shdr.sh_name = shstrtab.length(); 525 | shstrtab.append(".ARM.exidx"); 526 | shstrtab.push_back('\0'); 527 | 528 | shdr.sh_type = SHT_ARM_EXIDX; 529 | shdr.sh_flags = SHF_ALLOC | SHF_LINK_ORDER; 530 | shdr.sh_addr = (Elf_Addr)si.ARM_exidx - base; 531 | shdr.sh_offset = shdr.sh_addr; 532 | shdr.sh_size = si.ARM_exidx_count * sizeof(Elf_Addr); 533 | shdr.sh_link = sTEXTTAB; 534 | shdr.sh_info = 0; 535 | shdr.sh_addralign = 4; 536 | shdr.sh_entsize = 8; 537 | 538 | shdrs.push_back(shdr); 539 | } 540 | 541 | //generate .fini_array 542 | if(si.fini_array != nullptr){ 543 | memset((void*)&shdr, 0, sizeof(shdr)); 544 | sFINIARRAY = shdrs.size(); 545 | shdr.sh_name = shstrtab.length(); 546 | shstrtab.append(".fini_array"); 547 | shstrtab.push_back('\0'); 548 | 549 | shdr.sh_type = SHT_FINI_ARRAY; 550 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 551 | shdr.sh_addr = (Elf_Addr)si.fini_array - base; 552 | shdr.sh_offset = shdr.sh_addr; 553 | shdr.sh_size = si.fini_array_count * sizeof(Elf_Addr); 554 | shdr.sh_link = 0; 555 | shdr.sh_info = 0; 556 | shdr.sh_addralign = 4; 557 | shdr.sh_entsize = 0; 558 | 559 | shdrs.push_back(shdr); 560 | } 561 | 562 | //generate .init_array 563 | if(si.init_array != nullptr){ 564 | memset((void*)&shdr, 0, sizeof(shdr)); 565 | sINITARRAY = shdrs.size(); 566 | shdr.sh_name = shstrtab.length(); 567 | shstrtab.append(".init_array"); 568 | shstrtab.push_back('\0'); 569 | 570 | shdr.sh_type = SHT_INIT_ARRAY; 571 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 572 | shdr.sh_addr = (Elf_Addr)si.init_array - base; 573 | shdr.sh_offset = shdr.sh_addr; 574 | shdr.sh_size = si.init_array_count * sizeof(Elf_Addr); 575 | shdr.sh_link = 0; 576 | shdr.sh_info = 0; 577 | shdr.sh_addralign = 1; 578 | shdr.sh_entsize = 0; 579 | 580 | shdrs.push_back(shdr); 581 | } 582 | 583 | //generate .dynamic 584 | if(si.dynamic != nullptr){ 585 | memset((void*)&shdr, 0, sizeof(shdr)); 586 | sDYNAMIC = shdrs.size(); 587 | shdr.sh_name = shstrtab.length(); 588 | shstrtab.append(".dynamic"); 589 | shstrtab.push_back('\0'); 590 | 591 | shdr.sh_type = SHT_DYNAMIC; 592 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 593 | shdr.sh_addr = (Elf_Addr)si.dynamic - base; 594 | shdr.sh_offset = shdr.sh_addr; 595 | shdr.sh_size = si.dynamic_count * sizeof(Elf_Dyn); 596 | shdr.sh_link = sDYNSTR; 597 | shdr.sh_info = 0; 598 | shdr.sh_addralign = 4; 599 | shdr.sh_entsize = 8; 600 | 601 | shdrs.push_back(shdr); 602 | } 603 | 604 | //generate .got 605 | if(si.plt_got != nullptr){ 606 | memset((void*)&shdr, 0, sizeof(shdr)); 607 | sGOT = shdrs.size(); 608 | Elf_Word sLAST = sGOT - 1; 609 | shdr.sh_name = shstrtab.length(); 610 | shstrtab.append(".got"); 611 | shstrtab.push_back('\0'); 612 | 613 | shdr.sh_type = SHT_PROGBITS; 614 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 615 | shdr.sh_addr = shdrs[sLAST].sh_addr + shdrs[sLAST].sh_size; 616 | // In fact the .got is align 8. 617 | while(shdr.sh_addr & 0x7){ shdr.sh_addr++; } 618 | shdr.sh_offset = shdr.sh_addr; 619 | shdr.sh_size = (Elf_Addr)si.plt_got - base + 4*shdrs[sRELPLT].sh_size/sizeof(Elf_Rel) + 12 - shdr.sh_addr; 620 | shdr.sh_link = 0; 621 | shdr.sh_info = 0; 622 | shdr.sh_addralign = 4; 623 | shdr.sh_entsize = 0; 624 | 625 | shdrs.push_back(shdr); 626 | } 627 | 628 | //generate .data 629 | if(true){ 630 | memset((void*)&shdr, 0, sizeof(shdr)); 631 | sDATA = shdrs.size(); 632 | Elf_Word sLAST = sDATA - 1; 633 | shdr.sh_name = shstrtab.length(); 634 | shstrtab.append(".data"); 635 | shstrtab.push_back('\0'); 636 | 637 | shdr.sh_type = SHT_PROGBITS; 638 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 639 | shdr.sh_addr = shdrs[sLAST].sh_addr + shdrs[sLAST].sh_size; 640 | shdr.sh_offset = shdr.sh_addr; 641 | shdr.sh_size = si.loadSegEnd - shdr.sh_addr; 642 | shdr.sh_link = 0; 643 | shdr.sh_info = 0; 644 | shdr.sh_addralign = 4; 645 | shdr.sh_entsize = 0; 646 | 647 | shdrs.push_back(shdr); 648 | } 649 | 650 | //generate .bss 651 | if(true){ 652 | memset((void*)&shdr, 0, sizeof(shdr)); 653 | sBSS = shdrs.size(); 654 | Elf_Word sLAST = sBSS - 1; 655 | shdr.sh_name = shstrtab.length(); 656 | shstrtab.append(".bss"); 657 | shstrtab.push_back('\0'); 658 | 659 | shdr.sh_type = SHT_NOBITS; 660 | shdr.sh_flags = SHF_WRITE | SHF_ALLOC; 661 | shdr.sh_addr = shdrs[sLAST].sh_addr + shdrs[sLAST].sh_size; 662 | shdr.sh_offset = shdr.sh_addr; 663 | shdr.sh_size = 0; 664 | shdr.sh_link = 0; 665 | shdr.sh_info = 0; 666 | shdr.sh_addralign = 1; 667 | shdr.sh_entsize = 0; 668 | 669 | shdrs.push_back(shdr); 670 | } 671 | 672 | //generate .shstrtab 673 | memset((void*)&shdr, 0, sizeof(shdr)); 674 | sSHSTRTAB = shdrs.size(); 675 | shdr.sh_name = shstrtab.length(); 676 | shstrtab.append(".shstrtab"); 677 | shstrtab.push_back('\0'); 678 | 679 | shdr.sh_type = SHT_STRTAB; 680 | shdr.sh_flags = 0; 681 | shdr.sh_addr = 0; 682 | shdr.sh_offset = (Elf_Addr)si.max_load; 683 | shdr.sh_size = shstrtab.length(); 684 | shdr.sh_link = 0; 685 | shdr.sh_info = 0; 686 | shdr.sh_addralign = 1; 687 | shdr.sh_entsize = 0; 688 | 689 | shdrs.push_back(shdr); 690 | 691 | // patch the link section data 692 | if(sDYNSYM != 0){ 693 | shdrs[sDYNSYM].sh_link = sDYNSTR; 694 | } 695 | 696 | // sort shdr by address and recalc size 697 | for(int i = 1; i < shdrs.size(); i++) { 698 | for(int j = i + 1; j < shdrs.size(); j++) { 699 | if(shdrs[i].sh_offset > shdrs[j].sh_offset) { 700 | // exchange i, j 701 | Elf_Shdr tmp = shdrs[i]; 702 | shdrs[i] = shdrs[j]; 703 | shdrs[j] = tmp; 704 | 705 | // exchange index 706 | auto chgIdx = [i, j](Elf_Word &t) { 707 | if(t == i) { 708 | t = j; 709 | } else if(t == j) { 710 | t = i; 711 | } 712 | }; 713 | chgIdx(sDYNSYM); 714 | chgIdx(sDYNSTR); 715 | chgIdx(sHASH); 716 | chgIdx(sRELDYN); 717 | chgIdx(sRELPLT); 718 | chgIdx(sPLT); 719 | chgIdx(sTEXTTAB); 720 | chgIdx(sARMEXIDX); 721 | chgIdx(sFINIARRAY); 722 | chgIdx(sINITARRAY); 723 | chgIdx(sDYNAMIC); 724 | chgIdx(sGOT); 725 | chgIdx(sDATA); 726 | chgIdx(sBSS); 727 | chgIdx(sSHSTRTAB); 728 | } 729 | } 730 | } 731 | 732 | if(sTEXTTAB != 0){ 733 | shdrs[sTEXTTAB].sh_size = shdrs[sTEXTTAB + 1].sh_addr - shdrs[sTEXTTAB].sh_addr; 734 | } 735 | 736 | // recalculate the size of each section 737 | for(int i=2;igetType(); 760 | Elf_Word sym = rel->getSymbol(); 761 | 762 | Elf_Addr* prel = reinterpret_cast(base + rel->r_offset); 763 | if(type == 0) continue; //R_*_NONE 764 | switch(type){ 765 | // Only I know is RELATIVE. 766 | // It would add a load address when the got table 767 | // need to be relocated. 768 | // If the so file is dump from memory. The relocate 769 | // must have worked. We should subtract the load address. 770 | case R_386_RELATIVE: 771 | case R_ARM_RELATIVE: 772 | *prel = *prel - dump_base; 773 | break; 774 | default: 775 | break; 776 | } 777 | } 778 | }; 779 | relocate(si.load_bias, si.plt_rel, si.plt_rel_count, reader.getDumpSoBase()); 780 | relocate(si.load_bias, si.rel, si.plt_rel_count, reader.getDumpSoBase()); 781 | } 782 | return true; 783 | } 784 | 785 | bool ELFRebuilder::rebuildFinish(){ 786 | size_t load_size = si.max_load - si.min_load; 787 | rebuild_size = load_size + shstrtab.length() + shdrs.size()*sizeof(Elf_Shdr); 788 | 789 | if(rebuild_data != NULL) delete []rebuild_data; 790 | rebuild_data = new uint8_t[rebuild_size]; 791 | 792 | // load segment include elf header 793 | memcpy(rebuild_data, (void *)si.load_bias, load_size); 794 | // append shstrtab 795 | memcpy(rebuild_data + load_size, shstrtab.c_str(), shstrtab.length()); 796 | // append section table 797 | Elf_Off shdrOffset = load_size + shstrtab.length(); 798 | memcpy(rebuild_data + shdrOffset, (void*)&shdrs[0], shdrs.size()*sizeof(Elf_Shdr)); 799 | 800 | // repair the elf header 801 | elf_header.e_shoff = shdrOffset; 802 | elf_header.e_shentsize = sizeof(Elf_Shdr); 803 | elf_header.e_shnum = shdrs.size(); 804 | elf_header.e_shstrndx = sSHSTRTAB; 805 | memcpy(rebuild_data, &elf_header, sizeof(elf_header)); 806 | 807 | VLOG("Rebuild data prepared."); 808 | return true; 809 | } 810 | 811 | -------------------------------------------------------------------------------- /src/ELFRebuilder.h: -------------------------------------------------------------------------------- 1 | #ifndef _SO_REBUILDER_ELFREBUILDER_H_ 2 | #define _SO_REBUILDER_ELFREBUILDER_H_ 3 | 4 | #include 5 | #include 6 | #include "exutil.h" 7 | #include "ELFReader.h" 8 | 9 | /** 10 | * This structure are modified from android source. 11 | */ 12 | struct soinfo { 13 | public: 14 | const char* name = "name"; 15 | const Elf_Phdr* phdr = nullptr; 16 | size_t phnum = 0; 17 | Elf_Addr entry = 0; 18 | Elf_Addr base = 0; 19 | unsigned size = 0; 20 | 21 | Elf_Addr min_load; 22 | Elf_Addr max_load; 23 | 24 | uint32_t unused1 = 0; // DO NOT USE, maintained for compatibility. 25 | 26 | Elf_Dyn* dynamic = nullptr; 27 | size_t dynamic_count = 0; 28 | Elf_Word dynamic_flags = 0; 29 | 30 | uint32_t unused2 = 0; // DO NOT USE, maintained for compatibility 31 | uint32_t unused3 = 0; // DO NOT USE, maintained for compatibility 32 | 33 | unsigned flags = 0; 34 | 35 | const char* strtab = nullptr; 36 | Elf_Sym* symtab = nullptr; 37 | 38 | Elf_Addr hash = 0; 39 | size_t strtabsize = 0; 40 | size_t nbucket = 0; 41 | size_t nchain = 0; 42 | unsigned* bucket = nullptr; 43 | unsigned* chain = nullptr; 44 | 45 | Elf_Addr * plt_got = nullptr; 46 | 47 | Elf_Rel* plt_rel = nullptr; 48 | size_t plt_rel_count = 0; 49 | 50 | Elf_Rel* rel = nullptr; 51 | size_t rel_count = 0; 52 | 53 | void* preinit_array = nullptr; 54 | size_t preinit_array_count = 0; 55 | 56 | void** init_array = nullptr; 57 | size_t init_array_count = 0; 58 | void** fini_array = nullptr; 59 | size_t fini_array_count = 0; 60 | 61 | void* init_func = nullptr; 62 | void* fini_func = nullptr; 63 | 64 | // ARM EABI section used for stack unwinding. 65 | Elf_Addr * ARM_exidx = nullptr; 66 | unsigned ARM_exidx_count = 0; 67 | unsigned mips_symtabno = 0; 68 | unsigned mips_local_gotno = 0; 69 | unsigned mips_gotsym = 0; 70 | 71 | // When you read a virtual address from the ELF file, add this 72 | // value to get the corresponding address in the process' address space. 73 | Elf_Addr load_bias = 0; 74 | 75 | bool has_text_relocations = false; 76 | bool has_DT_SYMBOLIC = false; 77 | 78 | //Add by myself 79 | size_t dynsym_size = 0; 80 | Elf_Addr* interp = nullptr; 81 | size_t interp_size = 0; 82 | Elf_Addr loadSegEnd = 0; 83 | }; 84 | 85 | class ELFRebuilder{ 86 | 87 | public: 88 | 89 | ELFRebuilder(ELFReader &_reader, bool _force); 90 | ~ELFRebuilder(); 91 | bool rebuild(); 92 | uint8_t* getRebuildData() { return rebuild_data; } 93 | size_t getRebuildDataSize() { return rebuild_size; } 94 | private: 95 | 96 | bool force; // using to mark if force to rebuild the section. 97 | ELFReader &reader; 98 | 99 | Elf_Ehdr elf_header; 100 | Elf_Phdr *phdr_table; 101 | 102 | uint8_t *rebuild_data = NULL; 103 | size_t rebuild_size = 0; 104 | 105 | // Plan A 106 | bool simpleRebuild(); // just repair the section address and offset. 107 | bool rebuildData(); // restore data to rebuild_data. 108 | 109 | private: 110 | // Plan B 111 | bool totalRebuild(); // all rebuild. 112 | bool rebuildPhdr(); 113 | bool readSoInfo(); 114 | bool rebuildShdr(); 115 | bool rebuildRelocs(); 116 | bool rebuildFinish(); 117 | 118 | soinfo si; 119 | Elf_Word sINTERP = 0; 120 | Elf_Word sDYNSYM = 0; 121 | Elf_Word sDYNSTR = 0; 122 | Elf_Word sHASH = 0; 123 | Elf_Word sRELDYN = 0; 124 | Elf_Word sRELPLT = 0; 125 | Elf_Word sPLT = 0; 126 | Elf_Word sTEXTTAB = 0; 127 | Elf_Word sARMEXIDX = 0; 128 | Elf_Word sFINIARRAY = 0; 129 | Elf_Word sINITARRAY = 0; 130 | Elf_Word sDYNAMIC = 0; 131 | Elf_Word sGOT = 0; 132 | Elf_Word sDATA = 0; 133 | Elf_Word sBSS = 0; 134 | Elf_Word sSHSTRTAB = 0; 135 | 136 | std::vector shdrs; 137 | std::string shstrtab; 138 | }; 139 | 140 | 141 | 142 | #endif -------------------------------------------------------------------------------- /src/Log.cpp: -------------------------------------------------------------------------------- 1 | #include "Log.h" 2 | 3 | bool VERBOSE = false; 4 | bool DEBUG = false; -------------------------------------------------------------------------------- /src/Log.h: -------------------------------------------------------------------------------- 1 | #ifndef _SO_REBUILDER_LOG_H_ 2 | #define _SO_REBUILDER_LOG_H_ 3 | 4 | #include 5 | 6 | extern bool VERBOSE; 7 | extern bool DEBUG; 8 | 9 | 10 | #define NONE "\e[0m" // end of the ansi control 11 | #define BLUE "\e[0;34m" // Blue color, normal 12 | #define B_BLUE "\e[1;34m" // Blue color, bold 13 | #define RED "\e[0;31m" // Red color, normal 14 | #define B_RED "\e[1;31m" // Red color, bold 15 | #define YELLOW "\e[0;33m" // Yellow color 16 | 17 | 18 | #define VLOG(fmt, ...) if(VERBOSE) printf(YELLOW fmt "\n" NONE, ##__VA_ARGS__) //verbose log 19 | #define DLOG(fmt, ...) if(DEBUG) printf(B_BLUE "[DEBUG] " BLUE fmt "\n" NONE, ##__VA_ARGS__) //debug log 20 | #define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) //normal log 21 | #define ELOG(fmt, ...) printf(B_RED "[ERROR] " RED fmt "\n" NONE, ##__VA_ARGS__) //error log 22 | 23 | #endif -------------------------------------------------------------------------------- /src/elf.h: -------------------------------------------------------------------------------- 1 | //===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This header contains common, non-processor-specific data structures and 11 | // constants for the ELF file format. 12 | // 13 | // The details of the ELF32 bits in this file are largely based on the Tool 14 | // Interface Standard (TIS) Executable and Linking Format (ELF) Specification 15 | // Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format 16 | // Version 1.5, Draft 2, May 1998 as well as OpenBSD header files. 17 | // 18 | //===----------------------------------------------------------------------===// 19 | 20 | // BEGIN android-changed 21 | #ifndef ART_RUNTIME_ELF_H_ 22 | #define ART_RUNTIME_ELF_H_ 23 | // END android-changed 24 | 25 | // BEGIN android-changed 26 | #include 27 | #include 28 | // END android-changed 29 | 30 | typedef uint32_t Elf32_Addr; // Program address 31 | typedef uint32_t Elf32_Off; // File offset 32 | typedef uint16_t Elf32_Half; 33 | typedef uint32_t Elf32_Word; 34 | typedef int32_t Elf32_Sword; 35 | 36 | typedef uint64_t Elf64_Addr; 37 | typedef uint64_t Elf64_Off; 38 | typedef uint16_t Elf64_Half; 39 | typedef uint32_t Elf64_Word; 40 | typedef int32_t Elf64_Sword; 41 | typedef uint64_t Elf64_Xword; 42 | typedef int64_t Elf64_Sxword; 43 | 44 | // Object file magic string. 45 | static constexpr char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; 46 | 47 | // e_ident size and indices. 48 | enum { 49 | EI_MAG0 = 0, // File identification index. 50 | EI_MAG1 = 1, // File identification index. 51 | EI_MAG2 = 2, // File identification index. 52 | EI_MAG3 = 3, // File identification index. 53 | EI_CLASS = 4, // File class. 54 | EI_DATA = 5, // Data encoding. 55 | EI_VERSION = 6, // File version. 56 | EI_OSABI = 7, // OS/ABI identification. 57 | EI_ABIVERSION = 8, // ABI version. 58 | EI_PAD = 9, // Start of padding bytes. 59 | EI_NIDENT = 16 // Number of bytes in e_ident. 60 | }; 61 | 62 | // BEGIN android-added for compat 63 | constexpr char ELFMAG0 = ElfMagic[EI_MAG0]; 64 | constexpr char ELFMAG1 = ElfMagic[EI_MAG1]; 65 | constexpr char ELFMAG2 = ElfMagic[EI_MAG2]; 66 | constexpr char ELFMAG3 = ElfMagic[EI_MAG3]; 67 | // END android-added for compat 68 | 69 | struct Elf32_Ehdr { 70 | unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes 71 | Elf32_Half e_type; // Type of file (see ET_* below) 72 | Elf32_Half e_machine; // Required architecture for this file (see EM_*) 73 | Elf32_Word e_version; // Must be equal to 1 74 | Elf32_Addr e_entry; // Address to jump to in order to start program 75 | Elf32_Off e_phoff; // Program header table's file offset, in bytes 76 | Elf32_Off e_shoff; // Section header table's file offset, in bytes 77 | Elf32_Word e_flags; // Processor-specific flags 78 | Elf32_Half e_ehsize; // Size of ELF header, in bytes 79 | Elf32_Half e_phentsize; // Size of an entry in the program header table 80 | Elf32_Half e_phnum; // Number of entries in the program header table 81 | Elf32_Half e_shentsize; // Size of an entry in the section header table 82 | Elf32_Half e_shnum; // Number of entries in the section header table 83 | Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table 84 | bool checkMagic() const { 85 | return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; 86 | } 87 | unsigned char getFileClass() const { return e_ident[EI_CLASS]; } 88 | unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } 89 | }; 90 | 91 | // 64-bit ELF header. Fields are the same as for ELF32, but with different 92 | // types (see above). 93 | struct Elf64_Ehdr { 94 | unsigned char e_ident[EI_NIDENT]; 95 | Elf64_Half e_type; 96 | Elf64_Half e_machine; 97 | Elf64_Word e_version; 98 | Elf64_Addr e_entry; 99 | Elf64_Off e_phoff; 100 | Elf64_Off e_shoff; 101 | Elf64_Word e_flags; 102 | Elf64_Half e_ehsize; 103 | Elf64_Half e_phentsize; 104 | Elf64_Half e_phnum; 105 | Elf64_Half e_shentsize; 106 | Elf64_Half e_shnum; 107 | Elf64_Half e_shstrndx; 108 | bool checkMagic() const { 109 | return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; 110 | } 111 | unsigned char getFileClass() const { return e_ident[EI_CLASS]; } 112 | unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } 113 | }; 114 | 115 | // File types 116 | enum { 117 | ET_NONE = 0, // No file type 118 | ET_REL = 1, // Relocatable file 119 | ET_EXEC = 2, // Executable file 120 | ET_DYN = 3, // Shared object file 121 | ET_CORE = 4, // Core file 122 | ET_LOPROC = 0xff00, // Beginning of processor-specific codes 123 | ET_HIPROC = 0xffff // Processor-specific 124 | }; 125 | 126 | // Versioning 127 | enum { 128 | EV_NONE = 0, 129 | EV_CURRENT = 1 130 | }; 131 | 132 | // Machine architectures 133 | enum { 134 | EM_NONE = 0, // No machine 135 | EM_M32 = 1, // AT&T WE 32100 136 | EM_SPARC = 2, // SPARC 137 | EM_386 = 3, // Intel 386 138 | EM_68K = 4, // Motorola 68000 139 | EM_88K = 5, // Motorola 88000 140 | EM_486 = 6, // Intel 486 (deprecated) 141 | EM_860 = 7, // Intel 80860 142 | EM_MIPS = 8, // MIPS R3000 143 | EM_S370 = 9, // IBM System/370 144 | EM_MIPS_RS3_LE = 10, // MIPS RS3000 Little-endian 145 | EM_PARISC = 15, // Hewlett-Packard PA-RISC 146 | EM_VPP500 = 17, // Fujitsu VPP500 147 | EM_SPARC32PLUS = 18, // Enhanced instruction set SPARC 148 | EM_960 = 19, // Intel 80960 149 | EM_PPC = 20, // PowerPC 150 | EM_PPC64 = 21, // PowerPC64 151 | EM_S390 = 22, // IBM System/390 152 | EM_SPU = 23, // IBM SPU/SPC 153 | EM_V800 = 36, // NEC V800 154 | EM_FR20 = 37, // Fujitsu FR20 155 | EM_RH32 = 38, // TRW RH-32 156 | EM_RCE = 39, // Motorola RCE 157 | EM_ARM = 40, // ARM 158 | EM_ALPHA = 41, // DEC Alpha 159 | EM_SH = 42, // Hitachi SH 160 | EM_SPARCV9 = 43, // SPARC V9 161 | EM_TRICORE = 44, // Siemens TriCore 162 | EM_ARC = 45, // Argonaut RISC Core 163 | EM_H8_300 = 46, // Hitachi H8/300 164 | EM_H8_300H = 47, // Hitachi H8/300H 165 | EM_H8S = 48, // Hitachi H8S 166 | EM_H8_500 = 49, // Hitachi H8/500 167 | EM_IA_64 = 50, // Intel IA-64 processor architecture 168 | EM_MIPS_X = 51, // Stanford MIPS-X 169 | EM_COLDFIRE = 52, // Motorola ColdFire 170 | EM_68HC12 = 53, // Motorola M68HC12 171 | EM_MMA = 54, // Fujitsu MMA Multimedia Accelerator 172 | EM_PCP = 55, // Siemens PCP 173 | EM_NCPU = 56, // Sony nCPU embedded RISC processor 174 | EM_NDR1 = 57, // Denso NDR1 microprocessor 175 | EM_STARCORE = 58, // Motorola Star*Core processor 176 | EM_ME16 = 59, // Toyota ME16 processor 177 | EM_ST100 = 60, // STMicroelectronics ST100 processor 178 | EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor family 179 | EM_X86_64 = 62, // AMD x86-64 architecture 180 | EM_PDSP = 63, // Sony DSP Processor 181 | EM_PDP10 = 64, // Digital Equipment Corp. PDP-10 182 | EM_PDP11 = 65, // Digital Equipment Corp. PDP-11 183 | EM_FX66 = 66, // Siemens FX66 microcontroller 184 | EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller 185 | EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller 186 | EM_68HC16 = 69, // Motorola MC68HC16 Microcontroller 187 | EM_68HC11 = 70, // Motorola MC68HC11 Microcontroller 188 | EM_68HC08 = 71, // Motorola MC68HC08 Microcontroller 189 | EM_68HC05 = 72, // Motorola MC68HC05 Microcontroller 190 | EM_SVX = 73, // Silicon Graphics SVx 191 | EM_ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller 192 | EM_VAX = 75, // Digital VAX 193 | EM_CRIS = 76, // Axis Communications 32-bit embedded processor 194 | EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded processor 195 | EM_FIREPATH = 78, // Element 14 64-bit DSP Processor 196 | EM_ZSP = 79, // LSI Logic 16-bit DSP Processor 197 | EM_MMIX = 80, // Donald Knuth's educational 64-bit processor 198 | EM_HUANY = 81, // Harvard University machine-independent object files 199 | EM_PRISM = 82, // SiTera Prism 200 | EM_AVR = 83, // Atmel AVR 8-bit microcontroller 201 | EM_FR30 = 84, // Fujitsu FR30 202 | EM_D10V = 85, // Mitsubishi D10V 203 | EM_D30V = 86, // Mitsubishi D30V 204 | EM_V850 = 87, // NEC v850 205 | EM_M32R = 88, // Mitsubishi M32R 206 | EM_MN10300 = 89, // Matsushita MN10300 207 | EM_MN10200 = 90, // Matsushita MN10200 208 | EM_PJ = 91, // picoJava 209 | EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor 210 | EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old 211 | // spelling/synonym: EM_ARC_A5) 212 | EM_XTENSA = 94, // Tensilica Xtensa Architecture 213 | EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor 214 | EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor 215 | EM_NS32K = 97, // National Semiconductor 32000 series 216 | EM_TPC = 98, // Tenor Network TPC processor 217 | EM_SNP1K = 99, // Trebia SNP 1000 processor 218 | EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 219 | EM_IP2K = 101, // Ubicom IP2xxx microcontroller family 220 | EM_MAX = 102, // MAX Processor 221 | EM_CR = 103, // National Semiconductor CompactRISC microprocessor 222 | EM_F2MC16 = 104, // Fujitsu F2MC16 223 | EM_MSP430 = 105, // Texas Instruments embedded microcontroller msp430 224 | EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) processor 225 | EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors 226 | EM_SEP = 108, // Sharp embedded microprocessor 227 | EM_ARCA = 109, // Arca RISC Microprocessor 228 | EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC 229 | // of Peking University 230 | EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU 231 | EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor 232 | EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor 233 | EM_CRX = 114, // National Semiconductor CompactRISC CRX 234 | EM_XGATE = 115, // Motorola XGATE embedded processor 235 | EM_C166 = 116, // Infineon C16x/XC16x processor 236 | EM_M16C = 117, // Renesas M16C series microprocessors 237 | EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal 238 | // Controller 239 | EM_CE = 119, // Freescale Communication Engine RISC core 240 | EM_M32C = 120, // Renesas M32C series microprocessors 241 | EM_TSK3000 = 131, // Altium TSK3000 core 242 | EM_RS08 = 132, // Freescale RS08 embedded processor 243 | EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP 244 | // processors 245 | EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor 246 | EM_SCORE7 = 135, // Sunplus S+core7 RISC processor 247 | EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor 248 | EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor 249 | EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture 250 | EM_SE_C17 = 139, // Seiko Epson C17 family 251 | EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP family 252 | EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP family 253 | EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP family 254 | EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor 255 | EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor 256 | EM_R32C = 162, // Renesas R32C series microprocessors 257 | EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family 258 | EM_HEXAGON = 164, // Qualcomm Hexagon processor 259 | EM_8051 = 165, // Intel 8051 and variants 260 | EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable 261 | // and extensible RISC processors 262 | EM_NDS32 = 167, // Andes Technology compact code size embedded RISC 263 | // processor family 264 | EM_ECOG1 = 168, // Cyan Technology eCOG1X family 265 | EM_ECOG1X = 168, // Cyan Technology eCOG1X family 266 | EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers 267 | EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor 268 | EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor 269 | EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture 270 | EM_RX = 173, // Renesas RX family 271 | EM_METAG = 174, // Imagination Technologies META processor 272 | // architecture 273 | EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture 274 | EM_ECOG16 = 176, // Cyan Technology eCOG16 family 275 | EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit 276 | // microprocessor 277 | EM_ETPU = 178, // Freescale Extended Time Processing Unit 278 | EM_SLE9X = 179, // Infineon Technologies SLE9X core 279 | EM_L10M = 180, // Intel L10M 280 | EM_K10M = 181, // Intel K10M 281 | EM_AARCH64 = 183, // ARM AArch64 282 | EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family 283 | EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller 284 | EM_TILE64 = 187, // Tilera TILE64 multicore architecture family 285 | EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family 286 | EM_CUDA = 190, // NVIDIA CUDA architecture 287 | EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family 288 | EM_CLOUDSHIELD = 192, // CloudShield architecture family 289 | EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family 290 | EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family 291 | EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 292 | EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core 293 | EM_RL78 = 197, // Renesas RL78 family 294 | EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor 295 | EM_78KOR = 199, // Renesas 78KOR family 296 | EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) 297 | }; 298 | 299 | // Object file classes. 300 | enum { 301 | ELFCLASSNONE = 0, 302 | ELFCLASS32 = 1, // 32-bit object file 303 | ELFCLASS64 = 2 // 64-bit object file 304 | }; 305 | 306 | // Object file byte orderings. 307 | enum { 308 | ELFDATANONE = 0, // Invalid data encoding. 309 | ELFDATA2LSB = 1, // Little-endian object file 310 | ELFDATA2MSB = 2 // Big-endian object file 311 | }; 312 | 313 | // OS ABI identification. 314 | enum { 315 | ELFOSABI_NONE = 0, // UNIX System V ABI 316 | ELFOSABI_HPUX = 1, // HP-UX operating system 317 | ELFOSABI_NETBSD = 2, // NetBSD 318 | ELFOSABI_GNU = 3, // GNU/Linux 319 | ELFOSABI_LINUX = 3, // Historical alias for ELFOSABI_GNU. 320 | ELFOSABI_HURD = 4, // GNU/Hurd 321 | ELFOSABI_SOLARIS = 6, // Solaris 322 | ELFOSABI_AIX = 7, // AIX 323 | ELFOSABI_IRIX = 8, // IRIX 324 | ELFOSABI_FREEBSD = 9, // FreeBSD 325 | ELFOSABI_TRU64 = 10, // TRU64 UNIX 326 | ELFOSABI_MODESTO = 11, // Novell Modesto 327 | ELFOSABI_OPENBSD = 12, // OpenBSD 328 | ELFOSABI_OPENVMS = 13, // OpenVMS 329 | ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel 330 | ELFOSABI_AROS = 15, // AROS 331 | ELFOSABI_FENIXOS = 16, // FenixOS 332 | ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 333 | ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 334 | ELFOSABI_ARM = 97, // ARM 335 | ELFOSABI_STANDALONE = 255 // Standalone (embedded) application 336 | }; 337 | 338 | // X86_64 relocations. 339 | enum { 340 | R_X86_64_NONE = 0, 341 | R_X86_64_64 = 1, 342 | R_X86_64_PC32 = 2, 343 | R_X86_64_GOT32 = 3, 344 | R_X86_64_PLT32 = 4, 345 | R_X86_64_COPY = 5, 346 | R_X86_64_GLOB_DAT = 6, 347 | R_X86_64_JUMP_SLOT = 7, 348 | R_X86_64_RELATIVE = 8, 349 | R_X86_64_GOTPCREL = 9, 350 | R_X86_64_32 = 10, 351 | R_X86_64_32S = 11, 352 | R_X86_64_16 = 12, 353 | R_X86_64_PC16 = 13, 354 | R_X86_64_8 = 14, 355 | R_X86_64_PC8 = 15, 356 | R_X86_64_DTPMOD64 = 16, 357 | R_X86_64_DTPOFF64 = 17, 358 | R_X86_64_TPOFF64 = 18, 359 | R_X86_64_TLSGD = 19, 360 | R_X86_64_TLSLD = 20, 361 | R_X86_64_DTPOFF32 = 21, 362 | R_X86_64_GOTTPOFF = 22, 363 | R_X86_64_TPOFF32 = 23, 364 | R_X86_64_PC64 = 24, 365 | R_X86_64_GOTOFF64 = 25, 366 | R_X86_64_GOTPC32 = 26, 367 | R_X86_64_GOT64 = 27, 368 | R_X86_64_GOTPCREL64 = 28, 369 | R_X86_64_GOTPC64 = 29, 370 | R_X86_64_GOTPLT64 = 30, 371 | R_X86_64_PLTOFF64 = 31, 372 | R_X86_64_SIZE32 = 32, 373 | R_X86_64_SIZE64 = 33, 374 | R_X86_64_GOTPC32_TLSDESC = 34, 375 | R_X86_64_TLSDESC_CALL = 35, 376 | R_X86_64_TLSDESC = 36, 377 | R_X86_64_IRELATIVE = 37 378 | }; 379 | 380 | // i386 relocations. 381 | // TODO: this is just a subset 382 | enum { 383 | R_386_NONE = 0, 384 | R_386_32 = 1, 385 | R_386_PC32 = 2, 386 | R_386_GOT32 = 3, 387 | R_386_PLT32 = 4, 388 | R_386_COPY = 5, 389 | R_386_GLOB_DAT = 6, 390 | R_386_JUMP_SLOT = 7, 391 | R_386_RELATIVE = 8, 392 | R_386_GOTOFF = 9, 393 | R_386_GOTPC = 10, 394 | R_386_32PLT = 11, 395 | R_386_TLS_TPOFF = 14, 396 | R_386_TLS_IE = 15, 397 | R_386_TLS_GOTIE = 16, 398 | R_386_TLS_LE = 17, 399 | R_386_TLS_GD = 18, 400 | R_386_TLS_LDM = 19, 401 | R_386_16 = 20, 402 | R_386_PC16 = 21, 403 | R_386_8 = 22, 404 | R_386_PC8 = 23, 405 | R_386_TLS_GD_32 = 24, 406 | R_386_TLS_GD_PUSH = 25, 407 | R_386_TLS_GD_CALL = 26, 408 | R_386_TLS_GD_POP = 27, 409 | R_386_TLS_LDM_32 = 28, 410 | R_386_TLS_LDM_PUSH = 29, 411 | R_386_TLS_LDM_CALL = 30, 412 | R_386_TLS_LDM_POP = 31, 413 | R_386_TLS_LDO_32 = 32, 414 | R_386_TLS_IE_32 = 33, 415 | R_386_TLS_LE_32 = 34, 416 | R_386_TLS_DTPMOD32 = 35, 417 | R_386_TLS_DTPOFF32 = 36, 418 | R_386_TLS_TPOFF32 = 37, 419 | R_386_TLS_GOTDESC = 39, 420 | R_386_TLS_DESC_CALL = 40, 421 | R_386_TLS_DESC = 41, 422 | R_386_IRELATIVE = 42, 423 | R_386_NUM = 43 424 | }; 425 | 426 | // ELF Relocation types for PPC32 427 | enum { 428 | R_PPC_NONE = 0, /* No relocation. */ 429 | R_PPC_ADDR32 = 1, 430 | R_PPC_ADDR24 = 2, 431 | R_PPC_ADDR16 = 3, 432 | R_PPC_ADDR16_LO = 4, 433 | R_PPC_ADDR16_HI = 5, 434 | R_PPC_ADDR16_HA = 6, 435 | R_PPC_ADDR14 = 7, 436 | R_PPC_ADDR14_BRTAKEN = 8, 437 | R_PPC_ADDR14_BRNTAKEN = 9, 438 | R_PPC_REL24 = 10, 439 | R_PPC_REL14 = 11, 440 | R_PPC_REL14_BRTAKEN = 12, 441 | R_PPC_REL14_BRNTAKEN = 13, 442 | R_PPC_GOT16 = 14, 443 | R_PPC_GOT16_LO = 15, 444 | R_PPC_GOT16_HI = 16, 445 | R_PPC_GOT16_HA = 17, 446 | R_PPC_REL32 = 26, 447 | R_PPC_TLS = 67, 448 | R_PPC_DTPMOD32 = 68, 449 | R_PPC_TPREL16 = 69, 450 | R_PPC_TPREL16_LO = 70, 451 | R_PPC_TPREL16_HI = 71, 452 | R_PPC_TPREL16_HA = 72, 453 | R_PPC_TPREL32 = 73, 454 | R_PPC_DTPREL16 = 74, 455 | R_PPC_DTPREL16_LO = 75, 456 | R_PPC_DTPREL16_HI = 76, 457 | R_PPC_DTPREL16_HA = 77, 458 | R_PPC_DTPREL32 = 78, 459 | R_PPC_GOT_TLSGD16 = 79, 460 | R_PPC_GOT_TLSGD16_LO = 80, 461 | R_PPC_GOT_TLSGD16_HI = 81, 462 | R_PPC_GOT_TLSGD16_HA = 82, 463 | R_PPC_GOT_TLSLD16 = 83, 464 | R_PPC_GOT_TLSLD16_LO = 84, 465 | R_PPC_GOT_TLSLD16_HI = 85, 466 | R_PPC_GOT_TLSLD16_HA = 86, 467 | R_PPC_GOT_TPREL16 = 87, 468 | R_PPC_GOT_TPREL16_LO = 88, 469 | R_PPC_GOT_TPREL16_HI = 89, 470 | R_PPC_GOT_TPREL16_HA = 90, 471 | R_PPC_GOT_DTPREL16 = 91, 472 | R_PPC_GOT_DTPREL16_LO = 92, 473 | R_PPC_GOT_DTPREL16_HI = 93, 474 | R_PPC_GOT_DTPREL16_HA = 94, 475 | R_PPC_TLSGD = 95, 476 | R_PPC_TLSLD = 96, 477 | R_PPC_REL16 = 249, 478 | R_PPC_REL16_LO = 250, 479 | R_PPC_REL16_HI = 251, 480 | R_PPC_REL16_HA = 252 481 | }; 482 | 483 | // ELF Relocation types for PPC64 484 | enum { 485 | R_PPC64_NONE = 0, 486 | R_PPC64_ADDR32 = 1, 487 | R_PPC64_ADDR24 = 2, 488 | R_PPC64_ADDR16 = 3, 489 | R_PPC64_ADDR16_LO = 4, 490 | R_PPC64_ADDR16_HI = 5, 491 | R_PPC64_ADDR16_HA = 6, 492 | R_PPC64_ADDR14 = 7, 493 | R_PPC64_ADDR14_BRTAKEN = 8, 494 | R_PPC64_ADDR14_BRNTAKEN = 9, 495 | R_PPC64_REL24 = 10, 496 | R_PPC64_REL14 = 11, 497 | R_PPC64_REL14_BRTAKEN = 12, 498 | R_PPC64_REL14_BRNTAKEN = 13, 499 | R_PPC64_GOT16 = 14, 500 | R_PPC64_GOT16_LO = 15, 501 | R_PPC64_GOT16_HI = 16, 502 | R_PPC64_GOT16_HA = 17, 503 | R_PPC64_REL32 = 26, 504 | R_PPC64_ADDR64 = 38, 505 | R_PPC64_ADDR16_HIGHER = 39, 506 | R_PPC64_ADDR16_HIGHERA = 40, 507 | R_PPC64_ADDR16_HIGHEST = 41, 508 | R_PPC64_ADDR16_HIGHESTA = 42, 509 | R_PPC64_REL64 = 44, 510 | R_PPC64_TOC16 = 47, 511 | R_PPC64_TOC16_LO = 48, 512 | R_PPC64_TOC16_HI = 49, 513 | R_PPC64_TOC16_HA = 50, 514 | R_PPC64_TOC = 51, 515 | R_PPC64_ADDR16_DS = 56, 516 | R_PPC64_ADDR16_LO_DS = 57, 517 | R_PPC64_GOT16_DS = 58, 518 | R_PPC64_GOT16_LO_DS = 59, 519 | R_PPC64_TOC16_DS = 63, 520 | R_PPC64_TOC16_LO_DS = 64, 521 | R_PPC64_TLS = 67, 522 | R_PPC64_DTPMOD64 = 68, 523 | R_PPC64_TPREL16 = 69, 524 | R_PPC64_TPREL16_LO = 70, 525 | R_PPC64_TPREL16_HI = 71, 526 | R_PPC64_TPREL16_HA = 72, 527 | R_PPC64_TPREL64 = 73, 528 | R_PPC64_DTPREL16 = 74, 529 | R_PPC64_DTPREL16_LO = 75, 530 | R_PPC64_DTPREL16_HI = 76, 531 | R_PPC64_DTPREL16_HA = 77, 532 | R_PPC64_DTPREL64 = 78, 533 | R_PPC64_GOT_TLSGD16 = 79, 534 | R_PPC64_GOT_TLSGD16_LO = 80, 535 | R_PPC64_GOT_TLSGD16_HI = 81, 536 | R_PPC64_GOT_TLSGD16_HA = 82, 537 | R_PPC64_GOT_TLSLD16 = 83, 538 | R_PPC64_GOT_TLSLD16_LO = 84, 539 | R_PPC64_GOT_TLSLD16_HI = 85, 540 | R_PPC64_GOT_TLSLD16_HA = 86, 541 | R_PPC64_GOT_TPREL16_DS = 87, 542 | R_PPC64_GOT_TPREL16_LO_DS = 88, 543 | R_PPC64_GOT_TPREL16_HI = 89, 544 | R_PPC64_GOT_TPREL16_HA = 90, 545 | R_PPC64_GOT_DTPREL16_DS = 91, 546 | R_PPC64_GOT_DTPREL16_LO_DS = 92, 547 | R_PPC64_GOT_DTPREL16_HI = 93, 548 | R_PPC64_GOT_DTPREL16_HA = 94, 549 | R_PPC64_TPREL16_DS = 95, 550 | R_PPC64_TPREL16_LO_DS = 96, 551 | R_PPC64_TPREL16_HIGHER = 97, 552 | R_PPC64_TPREL16_HIGHERA = 98, 553 | R_PPC64_TPREL16_HIGHEST = 99, 554 | R_PPC64_TPREL16_HIGHESTA = 100, 555 | R_PPC64_DTPREL16_DS = 101, 556 | R_PPC64_DTPREL16_LO_DS = 102, 557 | R_PPC64_DTPREL16_HIGHER = 103, 558 | R_PPC64_DTPREL16_HIGHERA = 104, 559 | R_PPC64_DTPREL16_HIGHEST = 105, 560 | R_PPC64_DTPREL16_HIGHESTA = 106, 561 | R_PPC64_TLSGD = 107, 562 | R_PPC64_TLSLD = 108, 563 | R_PPC64_REL16 = 249, 564 | R_PPC64_REL16_LO = 250, 565 | R_PPC64_REL16_HI = 251, 566 | R_PPC64_REL16_HA = 252 567 | }; 568 | 569 | // ELF Relocation types for AArch64 570 | 571 | enum { 572 | R_AARCH64_NONE = 0x100, 573 | 574 | R_AARCH64_ABS64 = 0x101, 575 | R_AARCH64_ABS32 = 0x102, 576 | R_AARCH64_ABS16 = 0x103, 577 | R_AARCH64_PREL64 = 0x104, 578 | R_AARCH64_PREL32 = 0x105, 579 | R_AARCH64_PREL16 = 0x106, 580 | 581 | R_AARCH64_MOVW_UABS_G0 = 0x107, 582 | R_AARCH64_MOVW_UABS_G0_NC = 0x108, 583 | R_AARCH64_MOVW_UABS_G1 = 0x109, 584 | R_AARCH64_MOVW_UABS_G1_NC = 0x10a, 585 | R_AARCH64_MOVW_UABS_G2 = 0x10b, 586 | R_AARCH64_MOVW_UABS_G2_NC = 0x10c, 587 | R_AARCH64_MOVW_UABS_G3 = 0x10d, 588 | R_AARCH64_MOVW_SABS_G0 = 0x10e, 589 | R_AARCH64_MOVW_SABS_G1 = 0x10f, 590 | R_AARCH64_MOVW_SABS_G2 = 0x110, 591 | 592 | R_AARCH64_LD_PREL_LO19 = 0x111, 593 | R_AARCH64_ADR_PREL_LO21 = 0x112, 594 | R_AARCH64_ADR_PREL_PG_HI21 = 0x113, 595 | R_AARCH64_ADD_ABS_LO12_NC = 0x115, 596 | R_AARCH64_LDST8_ABS_LO12_NC = 0x116, 597 | 598 | R_AARCH64_TSTBR14 = 0x117, 599 | R_AARCH64_CONDBR19 = 0x118, 600 | R_AARCH64_JUMP26 = 0x11a, 601 | R_AARCH64_CALL26 = 0x11b, 602 | 603 | R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, 604 | R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, 605 | R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, 606 | 607 | R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, 608 | 609 | R_AARCH64_ADR_GOT_PAGE = 0x137, 610 | R_AARCH64_LD64_GOT_LO12_NC = 0x138, 611 | 612 | R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, 613 | R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, 614 | R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, 615 | R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, 616 | R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, 617 | R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, 618 | R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, 619 | R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, 620 | R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, 621 | R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, 622 | R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, 623 | R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, 624 | R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, 625 | R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, 626 | R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, 627 | R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, 628 | 629 | R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, 630 | R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, 631 | R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, 632 | R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, 633 | R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, 634 | 635 | R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, 636 | R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, 637 | R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, 638 | R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, 639 | R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, 640 | R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, 641 | R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, 642 | R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, 643 | R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, 644 | R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, 645 | R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, 646 | R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, 647 | R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, 648 | R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, 649 | R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, 650 | R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, 651 | 652 | R_AARCH64_TLSDESC_ADR_PAGE = 0x232, 653 | R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233, 654 | R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234, 655 | 656 | R_AARCH64_TLSDESC_CALL = 0x239 657 | }; 658 | 659 | // ARM Specific e_flags 660 | enum : unsigned { 661 | EF_ARM_SOFT_FLOAT = 0x00000200U, 662 | EF_ARM_VFP_FLOAT = 0x00000400U, 663 | EF_ARM_EABI_UNKNOWN = 0x00000000U, 664 | EF_ARM_EABI_VER1 = 0x01000000U, 665 | EF_ARM_EABI_VER2 = 0x02000000U, 666 | EF_ARM_EABI_VER3 = 0x03000000U, 667 | EF_ARM_EABI_VER4 = 0x04000000U, 668 | EF_ARM_EABI_VER5 = 0x05000000U, 669 | EF_ARM_EABIMASK = 0xFF000000U 670 | }; 671 | 672 | // ELF Relocation types for ARM 673 | // Meets 2.08 ABI Specs. 674 | 675 | enum { 676 | R_ARM_NONE = 0x00, 677 | R_ARM_PC24 = 0x01, 678 | R_ARM_ABS32 = 0x02, 679 | R_ARM_REL32 = 0x03, 680 | R_ARM_LDR_PC_G0 = 0x04, 681 | R_ARM_ABS16 = 0x05, 682 | R_ARM_ABS12 = 0x06, 683 | R_ARM_THM_ABS5 = 0x07, 684 | R_ARM_ABS8 = 0x08, 685 | R_ARM_SBREL32 = 0x09, 686 | R_ARM_THM_CALL = 0x0a, 687 | R_ARM_THM_PC8 = 0x0b, 688 | R_ARM_BREL_ADJ = 0x0c, 689 | R_ARM_TLS_DESC = 0x0d, 690 | R_ARM_THM_SWI8 = 0x0e, 691 | R_ARM_XPC25 = 0x0f, 692 | R_ARM_THM_XPC22 = 0x10, 693 | R_ARM_TLS_DTPMOD32 = 0x11, 694 | R_ARM_TLS_DTPOFF32 = 0x12, 695 | R_ARM_TLS_TPOFF32 = 0x13, 696 | R_ARM_COPY = 0x14, 697 | R_ARM_GLOB_DAT = 0x15, 698 | R_ARM_JUMP_SLOT = 0x16, 699 | R_ARM_RELATIVE = 0x17, 700 | R_ARM_GOTOFF32 = 0x18, 701 | R_ARM_BASE_PREL = 0x19, 702 | R_ARM_GOT_BREL = 0x1a, 703 | R_ARM_PLT32 = 0x1b, 704 | R_ARM_CALL = 0x1c, 705 | R_ARM_JUMP24 = 0x1d, 706 | R_ARM_THM_JUMP24 = 0x1e, 707 | R_ARM_BASE_ABS = 0x1f, 708 | R_ARM_ALU_PCREL_7_0 = 0x20, 709 | R_ARM_ALU_PCREL_15_8 = 0x21, 710 | R_ARM_ALU_PCREL_23_15 = 0x22, 711 | R_ARM_LDR_SBREL_11_0_NC = 0x23, 712 | R_ARM_ALU_SBREL_19_12_NC = 0x24, 713 | R_ARM_ALU_SBREL_27_20_CK = 0x25, 714 | R_ARM_TARGET1 = 0x26, 715 | R_ARM_SBREL31 = 0x27, 716 | R_ARM_V4BX = 0x28, 717 | R_ARM_TARGET2 = 0x29, 718 | R_ARM_PREL31 = 0x2a, 719 | R_ARM_MOVW_ABS_NC = 0x2b, 720 | R_ARM_MOVT_ABS = 0x2c, 721 | R_ARM_MOVW_PREL_NC = 0x2d, 722 | R_ARM_MOVT_PREL = 0x2e, 723 | R_ARM_THM_MOVW_ABS_NC = 0x2f, 724 | R_ARM_THM_MOVT_ABS = 0x30, 725 | R_ARM_THM_MOVW_PREL_NC = 0x31, 726 | R_ARM_THM_MOVT_PREL = 0x32, 727 | R_ARM_THM_JUMP19 = 0x33, 728 | R_ARM_THM_JUMP6 = 0x34, 729 | R_ARM_THM_ALU_PREL_11_0 = 0x35, 730 | R_ARM_THM_PC12 = 0x36, 731 | R_ARM_ABS32_NOI = 0x37, 732 | R_ARM_REL32_NOI = 0x38, 733 | R_ARM_ALU_PC_G0_NC = 0x39, 734 | R_ARM_ALU_PC_G0 = 0x3a, 735 | R_ARM_ALU_PC_G1_NC = 0x3b, 736 | R_ARM_ALU_PC_G1 = 0x3c, 737 | R_ARM_ALU_PC_G2 = 0x3d, 738 | R_ARM_LDR_PC_G1 = 0x3e, 739 | R_ARM_LDR_PC_G2 = 0x3f, 740 | R_ARM_LDRS_PC_G0 = 0x40, 741 | R_ARM_LDRS_PC_G1 = 0x41, 742 | R_ARM_LDRS_PC_G2 = 0x42, 743 | R_ARM_LDC_PC_G0 = 0x43, 744 | R_ARM_LDC_PC_G1 = 0x44, 745 | R_ARM_LDC_PC_G2 = 0x45, 746 | R_ARM_ALU_SB_G0_NC = 0x46, 747 | R_ARM_ALU_SB_G0 = 0x47, 748 | R_ARM_ALU_SB_G1_NC = 0x48, 749 | R_ARM_ALU_SB_G1 = 0x49, 750 | R_ARM_ALU_SB_G2 = 0x4a, 751 | R_ARM_LDR_SB_G0 = 0x4b, 752 | R_ARM_LDR_SB_G1 = 0x4c, 753 | R_ARM_LDR_SB_G2 = 0x4d, 754 | R_ARM_LDRS_SB_G0 = 0x4e, 755 | R_ARM_LDRS_SB_G1 = 0x4f, 756 | R_ARM_LDRS_SB_G2 = 0x50, 757 | R_ARM_LDC_SB_G0 = 0x51, 758 | R_ARM_LDC_SB_G1 = 0x52, 759 | R_ARM_LDC_SB_G2 = 0x53, 760 | R_ARM_MOVW_BREL_NC = 0x54, 761 | R_ARM_MOVT_BREL = 0x55, 762 | R_ARM_MOVW_BREL = 0x56, 763 | R_ARM_THM_MOVW_BREL_NC = 0x57, 764 | R_ARM_THM_MOVT_BREL = 0x58, 765 | R_ARM_THM_MOVW_BREL = 0x59, 766 | R_ARM_TLS_GOTDESC = 0x5a, 767 | R_ARM_TLS_CALL = 0x5b, 768 | R_ARM_TLS_DESCSEQ = 0x5c, 769 | R_ARM_THM_TLS_CALL = 0x5d, 770 | R_ARM_PLT32_ABS = 0x5e, 771 | R_ARM_GOT_ABS = 0x5f, 772 | R_ARM_GOT_PREL = 0x60, 773 | R_ARM_GOT_BREL12 = 0x61, 774 | R_ARM_GOTOFF12 = 0x62, 775 | R_ARM_GOTRELAX = 0x63, 776 | R_ARM_GNU_VTENTRY = 0x64, 777 | R_ARM_GNU_VTINHERIT = 0x65, 778 | R_ARM_THM_JUMP11 = 0x66, 779 | R_ARM_THM_JUMP8 = 0x67, 780 | R_ARM_TLS_GD32 = 0x68, 781 | R_ARM_TLS_LDM32 = 0x69, 782 | R_ARM_TLS_LDO32 = 0x6a, 783 | R_ARM_TLS_IE32 = 0x6b, 784 | R_ARM_TLS_LE32 = 0x6c, 785 | R_ARM_TLS_LDO12 = 0x6d, 786 | R_ARM_TLS_LE12 = 0x6e, 787 | R_ARM_TLS_IE12GP = 0x6f, 788 | R_ARM_PRIVATE_0 = 0x70, 789 | R_ARM_PRIVATE_1 = 0x71, 790 | R_ARM_PRIVATE_2 = 0x72, 791 | R_ARM_PRIVATE_3 = 0x73, 792 | R_ARM_PRIVATE_4 = 0x74, 793 | R_ARM_PRIVATE_5 = 0x75, 794 | R_ARM_PRIVATE_6 = 0x76, 795 | R_ARM_PRIVATE_7 = 0x77, 796 | R_ARM_PRIVATE_8 = 0x78, 797 | R_ARM_PRIVATE_9 = 0x79, 798 | R_ARM_PRIVATE_10 = 0x7a, 799 | R_ARM_PRIVATE_11 = 0x7b, 800 | R_ARM_PRIVATE_12 = 0x7c, 801 | R_ARM_PRIVATE_13 = 0x7d, 802 | R_ARM_PRIVATE_14 = 0x7e, 803 | R_ARM_PRIVATE_15 = 0x7f, 804 | R_ARM_ME_TOO = 0x80, 805 | R_ARM_THM_TLS_DESCSEQ16 = 0x81, 806 | R_ARM_THM_TLS_DESCSEQ32 = 0x82 807 | }; 808 | 809 | // Mips Specific e_flags 810 | enum : unsigned { 811 | EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions 812 | EF_MIPS_PIC = 0x00000002, // Position independent code 813 | EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code 814 | EF_MIPS_ABI2 = 0x00000020, 815 | EF_MIPS_32BITMODE = 0x00000100, 816 | EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding 817 | EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI 818 | 819 | //ARCH_ASE 820 | EF_MIPS_MICROMIPS = 0x02000000, // microMIPS 821 | EF_MIPS_ARCH_ASE_M16 = 822 | 0x04000000, // Has Mips-16 ISA extensions 823 | //ARCH 824 | EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set 825 | EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set 826 | EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set 827 | EF_MIPS_ARCH_4 = 0x30000000, // MIPS4 instruction set 828 | EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set 829 | EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h 830 | EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h 831 | EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2 832 | EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2 833 | EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 834 | EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 835 | EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant 836 | }; 837 | 838 | // ELF Relocation types for Mips 839 | enum { 840 | R_MIPS_NONE = 0, 841 | R_MIPS_16 = 1, 842 | R_MIPS_32 = 2, 843 | R_MIPS_REL32 = 3, 844 | R_MIPS_26 = 4, 845 | R_MIPS_HI16 = 5, 846 | R_MIPS_LO16 = 6, 847 | R_MIPS_GPREL16 = 7, 848 | R_MIPS_LITERAL = 8, 849 | R_MIPS_GOT16 = 9, 850 | R_MIPS_PC16 = 10, 851 | R_MIPS_CALL16 = 11, 852 | R_MIPS_GPREL32 = 12, 853 | R_MIPS_UNUSED1 = 13, 854 | R_MIPS_UNUSED2 = 14, 855 | R_MIPS_SHIFT5 = 16, 856 | R_MIPS_SHIFT6 = 17, 857 | R_MIPS_64 = 18, 858 | R_MIPS_GOT_DISP = 19, 859 | R_MIPS_GOT_PAGE = 20, 860 | R_MIPS_GOT_OFST = 21, 861 | R_MIPS_GOT_HI16 = 22, 862 | R_MIPS_GOT_LO16 = 23, 863 | R_MIPS_SUB = 24, 864 | R_MIPS_INSERT_A = 25, 865 | R_MIPS_INSERT_B = 26, 866 | R_MIPS_DELETE = 27, 867 | R_MIPS_HIGHER = 28, 868 | R_MIPS_HIGHEST = 29, 869 | R_MIPS_CALL_HI16 = 30, 870 | R_MIPS_CALL_LO16 = 31, 871 | R_MIPS_SCN_DISP = 32, 872 | R_MIPS_REL16 = 33, 873 | R_MIPS_ADD_IMMEDIATE = 34, 874 | R_MIPS_PJUMP = 35, 875 | R_MIPS_RELGOT = 36, 876 | R_MIPS_JALR = 37, 877 | R_MIPS_TLS_DTPMOD32 = 38, 878 | R_MIPS_TLS_DTPREL32 = 39, 879 | R_MIPS_TLS_DTPMOD64 = 40, 880 | R_MIPS_TLS_DTPREL64 = 41, 881 | R_MIPS_TLS_GD = 42, 882 | R_MIPS_TLS_LDM = 43, 883 | R_MIPS_TLS_DTPREL_HI16 = 44, 884 | R_MIPS_TLS_DTPREL_LO16 = 45, 885 | R_MIPS_TLS_GOTTPREL = 46, 886 | R_MIPS_TLS_TPREL32 = 47, 887 | R_MIPS_TLS_TPREL64 = 48, 888 | R_MIPS_TLS_TPREL_HI16 = 49, 889 | R_MIPS_TLS_TPREL_LO16 = 50, 890 | R_MIPS_GLOB_DAT = 51, 891 | R_MIPS_PC21_S2 = 60, 892 | R_MIPS_PC26_S2 = 61, 893 | R_MIPS_PC18_S3 = 62, 894 | R_MIPS_PC19_S2 = 63, 895 | R_MIPS_PCHI16 = 64, 896 | R_MIPS_PCLO16 = 65, 897 | R_MIPS16_GOT16 = 102, 898 | R_MIPS16_HI16 = 104, 899 | R_MIPS16_LO16 = 105, 900 | R_MIPS_COPY = 126, 901 | R_MIPS_JUMP_SLOT = 127, 902 | R_MICROMIPS_26_S1 = 133, 903 | R_MICROMIPS_HI16 = 134, 904 | R_MICROMIPS_LO16 = 135, 905 | R_MICROMIPS_GOT16 = 138, 906 | R_MICROMIPS_PC16_S1 = 141, 907 | R_MICROMIPS_CALL16 = 142, 908 | R_MICROMIPS_GOT_DISP = 145, 909 | R_MICROMIPS_GOT_PAGE = 146, 910 | R_MICROMIPS_GOT_OFST = 147, 911 | R_MICROMIPS_TLS_GD = 162, 912 | R_MICROMIPS_TLS_LDM = 163, 913 | R_MICROMIPS_TLS_DTPREL_HI16 = 164, 914 | R_MICROMIPS_TLS_DTPREL_LO16 = 165, 915 | R_MICROMIPS_TLS_TPREL_HI16 = 169, 916 | R_MICROMIPS_TLS_TPREL_LO16 = 170, 917 | R_MIPS_NUM = 218, 918 | R_MIPS_PC32 = 248 919 | }; 920 | 921 | // Special values for the st_other field in the symbol table entry for MIPS. 922 | enum { 923 | STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional 924 | STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record 925 | STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC 926 | STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips 927 | STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 928 | }; 929 | 930 | // Hexagon Specific e_flags 931 | // Release 5 ABI 932 | enum { 933 | // Object processor version flags, bits[3:0] 934 | EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 935 | EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 936 | EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 937 | EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 938 | 939 | // Highest ISA version flags 940 | EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[3:0] 941 | // of e_flags 942 | EF_HEXAGON_ISA_V2 = 0x00000010, // Hexagon V2 ISA 943 | EF_HEXAGON_ISA_V3 = 0x00000020, // Hexagon V3 ISA 944 | EF_HEXAGON_ISA_V4 = 0x00000030, // Hexagon V4 ISA 945 | EF_HEXAGON_ISA_V5 = 0x00000040 // Hexagon V5 ISA 946 | }; 947 | 948 | // Hexagon specific Section indexes for common small data 949 | // Release 5 ABI 950 | enum { 951 | SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes 952 | SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access 953 | SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access 954 | SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access 955 | SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access 956 | }; 957 | 958 | // ELF Relocation types for Hexagon 959 | // Release 5 ABI 960 | enum { 961 | R_HEX_NONE = 0, 962 | R_HEX_B22_PCREL = 1, 963 | R_HEX_B15_PCREL = 2, 964 | R_HEX_B7_PCREL = 3, 965 | R_HEX_LO16 = 4, 966 | R_HEX_HI16 = 5, 967 | R_HEX_32 = 6, 968 | R_HEX_16 = 7, 969 | R_HEX_8 = 8, 970 | R_HEX_GPREL16_0 = 9, 971 | R_HEX_GPREL16_1 = 10, 972 | R_HEX_GPREL16_2 = 11, 973 | R_HEX_GPREL16_3 = 12, 974 | R_HEX_HL16 = 13, 975 | R_HEX_B13_PCREL = 14, 976 | R_HEX_B9_PCREL = 15, 977 | R_HEX_B32_PCREL_X = 16, 978 | R_HEX_32_6_X = 17, 979 | R_HEX_B22_PCREL_X = 18, 980 | R_HEX_B15_PCREL_X = 19, 981 | R_HEX_B13_PCREL_X = 20, 982 | R_HEX_B9_PCREL_X = 21, 983 | R_HEX_B7_PCREL_X = 22, 984 | R_HEX_16_X = 23, 985 | R_HEX_12_X = 24, 986 | R_HEX_11_X = 25, 987 | R_HEX_10_X = 26, 988 | R_HEX_9_X = 27, 989 | R_HEX_8_X = 28, 990 | R_HEX_7_X = 29, 991 | R_HEX_6_X = 30, 992 | R_HEX_32_PCREL = 31, 993 | R_HEX_COPY = 32, 994 | R_HEX_GLOB_DAT = 33, 995 | R_HEX_JMP_SLOT = 34, 996 | R_HEX_RELATIVE = 35, 997 | R_HEX_PLT_B22_PCREL = 36, 998 | R_HEX_GOTREL_LO16 = 37, 999 | R_HEX_GOTREL_HI16 = 38, 1000 | R_HEX_GOTREL_32 = 39, 1001 | R_HEX_GOT_LO16 = 40, 1002 | R_HEX_GOT_HI16 = 41, 1003 | R_HEX_GOT_32 = 42, 1004 | R_HEX_GOT_16 = 43, 1005 | R_HEX_DTPMOD_32 = 44, 1006 | R_HEX_DTPREL_LO16 = 45, 1007 | R_HEX_DTPREL_HI16 = 46, 1008 | R_HEX_DTPREL_32 = 47, 1009 | R_HEX_DTPREL_16 = 48, 1010 | R_HEX_GD_PLT_B22_PCREL = 49, 1011 | R_HEX_GD_GOT_LO16 = 50, 1012 | R_HEX_GD_GOT_HI16 = 51, 1013 | R_HEX_GD_GOT_32 = 52, 1014 | R_HEX_GD_GOT_16 = 53, 1015 | R_HEX_IE_LO16 = 54, 1016 | R_HEX_IE_HI16 = 55, 1017 | R_HEX_IE_32 = 56, 1018 | R_HEX_IE_GOT_LO16 = 57, 1019 | R_HEX_IE_GOT_HI16 = 58, 1020 | R_HEX_IE_GOT_32 = 59, 1021 | R_HEX_IE_GOT_16 = 60, 1022 | R_HEX_TPREL_LO16 = 61, 1023 | R_HEX_TPREL_HI16 = 62, 1024 | R_HEX_TPREL_32 = 63, 1025 | R_HEX_TPREL_16 = 64, 1026 | R_HEX_6_PCREL_X = 65, 1027 | R_HEX_GOTREL_32_6_X = 66, 1028 | R_HEX_GOTREL_16_X = 67, 1029 | R_HEX_GOTREL_11_X = 68, 1030 | R_HEX_GOT_32_6_X = 69, 1031 | R_HEX_GOT_16_X = 70, 1032 | R_HEX_GOT_11_X = 71, 1033 | R_HEX_DTPREL_32_6_X = 72, 1034 | R_HEX_DTPREL_16_X = 73, 1035 | R_HEX_DTPREL_11_X = 74, 1036 | R_HEX_GD_GOT_32_6_X = 75, 1037 | R_HEX_GD_GOT_16_X = 76, 1038 | R_HEX_GD_GOT_11_X = 77, 1039 | R_HEX_IE_32_6_X = 78, 1040 | R_HEX_IE_16_X = 79, 1041 | R_HEX_IE_GOT_32_6_X = 80, 1042 | R_HEX_IE_GOT_16_X = 81, 1043 | R_HEX_IE_GOT_11_X = 82, 1044 | R_HEX_TPREL_32_6_X = 83, 1045 | R_HEX_TPREL_16_X = 84, 1046 | R_HEX_TPREL_11_X = 85 1047 | }; 1048 | 1049 | // ELF Relocation types for S390/zSeries 1050 | enum { 1051 | R_390_NONE = 0, 1052 | R_390_8 = 1, 1053 | R_390_12 = 2, 1054 | R_390_16 = 3, 1055 | R_390_32 = 4, 1056 | R_390_PC32 = 5, 1057 | R_390_GOT12 = 6, 1058 | R_390_GOT32 = 7, 1059 | R_390_PLT32 = 8, 1060 | R_390_COPY = 9, 1061 | R_390_GLOB_DAT = 10, 1062 | R_390_JMP_SLOT = 11, 1063 | R_390_RELATIVE = 12, 1064 | R_390_GOTOFF = 13, 1065 | R_390_GOTPC = 14, 1066 | R_390_GOT16 = 15, 1067 | R_390_PC16 = 16, 1068 | R_390_PC16DBL = 17, 1069 | R_390_PLT16DBL = 18, 1070 | R_390_PC32DBL = 19, 1071 | R_390_PLT32DBL = 20, 1072 | R_390_GOTPCDBL = 21, 1073 | R_390_64 = 22, 1074 | R_390_PC64 = 23, 1075 | R_390_GOT64 = 24, 1076 | R_390_PLT64 = 25, 1077 | R_390_GOTENT = 26, 1078 | R_390_GOTOFF16 = 27, 1079 | R_390_GOTOFF64 = 28, 1080 | R_390_GOTPLT12 = 29, 1081 | R_390_GOTPLT16 = 30, 1082 | R_390_GOTPLT32 = 31, 1083 | R_390_GOTPLT64 = 32, 1084 | R_390_GOTPLTENT = 33, 1085 | R_390_PLTOFF16 = 34, 1086 | R_390_PLTOFF32 = 35, 1087 | R_390_PLTOFF64 = 36, 1088 | R_390_TLS_LOAD = 37, 1089 | R_390_TLS_GDCALL = 38, 1090 | R_390_TLS_LDCALL = 39, 1091 | R_390_TLS_GD32 = 40, 1092 | R_390_TLS_GD64 = 41, 1093 | R_390_TLS_GOTIE12 = 42, 1094 | R_390_TLS_GOTIE32 = 43, 1095 | R_390_TLS_GOTIE64 = 44, 1096 | R_390_TLS_LDM32 = 45, 1097 | R_390_TLS_LDM64 = 46, 1098 | R_390_TLS_IE32 = 47, 1099 | R_390_TLS_IE64 = 48, 1100 | R_390_TLS_IEENT = 49, 1101 | R_390_TLS_LE32 = 50, 1102 | R_390_TLS_LE64 = 51, 1103 | R_390_TLS_LDO32 = 52, 1104 | R_390_TLS_LDO64 = 53, 1105 | R_390_TLS_DTPMOD = 54, 1106 | R_390_TLS_DTPOFF = 55, 1107 | R_390_TLS_TPOFF = 56, 1108 | R_390_20 = 57, 1109 | R_390_GOT20 = 58, 1110 | R_390_GOTPLT20 = 59, 1111 | R_390_TLS_GOTIE20 = 60, 1112 | R_390_IRELATIVE = 61 1113 | }; 1114 | 1115 | // ELF Relocation type for Sparc. 1116 | enum { 1117 | R_SPARC_NONE = 0, 1118 | R_SPARC_8 = 1, 1119 | R_SPARC_16 = 2, 1120 | R_SPARC_32 = 3, 1121 | R_SPARC_DISP8 = 4, 1122 | R_SPARC_DISP16 = 5, 1123 | R_SPARC_DISP32 = 6, 1124 | R_SPARC_WDISP30 = 7, 1125 | R_SPARC_WDISP22 = 8, 1126 | R_SPARC_HI22 = 9, 1127 | R_SPARC_22 = 10, 1128 | R_SPARC_13 = 11, 1129 | R_SPARC_LO10 = 12, 1130 | R_SPARC_GOT10 = 13, 1131 | R_SPARC_GOT13 = 14, 1132 | R_SPARC_GOT22 = 15, 1133 | R_SPARC_PC10 = 16, 1134 | R_SPARC_PC22 = 17, 1135 | R_SPARC_WPLT30 = 18, 1136 | R_SPARC_COPY = 19, 1137 | R_SPARC_GLOB_DAT = 20, 1138 | R_SPARC_JMP_SLOT = 21, 1139 | R_SPARC_RELATIVE = 22, 1140 | R_SPARC_UA32 = 23, 1141 | R_SPARC_PLT32 = 24, 1142 | R_SPARC_HIPLT22 = 25, 1143 | R_SPARC_LOPLT10 = 26, 1144 | R_SPARC_PCPLT32 = 27, 1145 | R_SPARC_PCPLT22 = 28, 1146 | R_SPARC_PCPLT10 = 29, 1147 | R_SPARC_10 = 30, 1148 | R_SPARC_11 = 31, 1149 | R_SPARC_64 = 32, 1150 | R_SPARC_OLO10 = 33, 1151 | R_SPARC_HH22 = 34, 1152 | R_SPARC_HM10 = 35, 1153 | R_SPARC_LM22 = 36, 1154 | R_SPARC_PC_HH22 = 37, 1155 | R_SPARC_PC_HM10 = 38, 1156 | R_SPARC_PC_LM22 = 39, 1157 | R_SPARC_WDISP16 = 40, 1158 | R_SPARC_WDISP19 = 41, 1159 | R_SPARC_7 = 43, 1160 | R_SPARC_5 = 44, 1161 | R_SPARC_6 = 45, 1162 | R_SPARC_DISP64 = 46, 1163 | R_SPARC_PLT64 = 47, 1164 | R_SPARC_HIX22 = 48, 1165 | R_SPARC_LOX10 = 49, 1166 | R_SPARC_H44 = 50, 1167 | R_SPARC_M44 = 51, 1168 | R_SPARC_L44 = 52, 1169 | R_SPARC_REGISTER = 53, 1170 | R_SPARC_UA64 = 54, 1171 | R_SPARC_UA16 = 55, 1172 | R_SPARC_TLS_GD_HI22 = 56, 1173 | R_SPARC_TLS_GD_LO10 = 57, 1174 | R_SPARC_TLS_GD_ADD = 58, 1175 | R_SPARC_TLS_GD_CALL = 59, 1176 | R_SPARC_TLS_LDM_HI22 = 60, 1177 | R_SPARC_TLS_LDM_LO10 = 61, 1178 | R_SPARC_TLS_LDM_ADD = 62, 1179 | R_SPARC_TLS_LDM_CALL = 63, 1180 | R_SPARC_TLS_LDO_HIX22 = 64, 1181 | R_SPARC_TLS_LDO_LOX10 = 65, 1182 | R_SPARC_TLS_LDO_ADD = 66, 1183 | R_SPARC_TLS_IE_HI22 = 67, 1184 | R_SPARC_TLS_IE_LO10 = 68, 1185 | R_SPARC_TLS_IE_LD = 69, 1186 | R_SPARC_TLS_IE_LDX = 70, 1187 | R_SPARC_TLS_IE_ADD = 71, 1188 | R_SPARC_TLS_LE_HIX22 = 72, 1189 | R_SPARC_TLS_LE_LOX10 = 73, 1190 | R_SPARC_TLS_DTPMOD32 = 74, 1191 | R_SPARC_TLS_DTPMOD64 = 75, 1192 | R_SPARC_TLS_DTPOFF32 = 76, 1193 | R_SPARC_TLS_DTPOFF64 = 77, 1194 | R_SPARC_TLS_TPOFF32 = 78, 1195 | R_SPARC_TLS_TPOFF64 = 79, 1196 | R_SPARC_GOTDATA_HIX22 = 80, 1197 | R_SPARC_GOTDATA_LOX22 = 81, 1198 | R_SPARC_GOTDATA_OP_HIX22 = 82, 1199 | R_SPARC_GOTDATA_OP_LOX22 = 83, 1200 | R_SPARC_GOTDATA_OP = 84 1201 | }; 1202 | 1203 | // Section header. 1204 | struct Elf32_Shdr { 1205 | Elf32_Word sh_name; // Section name (index into string table) 1206 | Elf32_Word sh_type; // Section type (SHT_*) 1207 | Elf32_Word sh_flags; // Section flags (SHF_*) 1208 | Elf32_Addr sh_addr; // Address where section is to be loaded 1209 | Elf32_Off sh_offset; // File offset of section data, in bytes 1210 | Elf32_Word sh_size; // Size of section, in bytes 1211 | Elf32_Word sh_link; // Section type-specific header table index link 1212 | Elf32_Word sh_info; // Section type-specific extra information 1213 | Elf32_Word sh_addralign; // Section address alignment 1214 | Elf32_Word sh_entsize; // Size of records contained within the section 1215 | }; 1216 | 1217 | // Section header for ELF64 - same fields as ELF32, different types. 1218 | struct Elf64_Shdr { 1219 | Elf64_Word sh_name; 1220 | Elf64_Word sh_type; 1221 | Elf64_Xword sh_flags; 1222 | Elf64_Addr sh_addr; 1223 | Elf64_Off sh_offset; 1224 | Elf64_Xword sh_size; 1225 | Elf64_Word sh_link; 1226 | Elf64_Word sh_info; 1227 | Elf64_Xword sh_addralign; 1228 | Elf64_Xword sh_entsize; 1229 | }; 1230 | 1231 | // Special section indices. 1232 | enum { 1233 | SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless 1234 | SHN_LORESERVE = 0xff00, // Lowest reserved index 1235 | SHN_LOPROC = 0xff00, // Lowest processor-specific index 1236 | SHN_HIPROC = 0xff1f, // Highest processor-specific index 1237 | SHN_LOOS = 0xff20, // Lowest operating system-specific index 1238 | SHN_HIOS = 0xff3f, // Highest operating system-specific index 1239 | SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation 1240 | SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables 1241 | SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE 1242 | SHN_HIRESERVE = 0xffff // Highest reserved index 1243 | }; 1244 | 1245 | // Section types. 1246 | enum : unsigned { 1247 | SHT_NULL = 0, // No associated section (inactive entry). 1248 | SHT_PROGBITS = 1, // Program-defined contents. 1249 | SHT_SYMTAB = 2, // Symbol table. 1250 | SHT_STRTAB = 3, // String table. 1251 | SHT_RELA = 4, // Relocation entries; explicit addends. 1252 | SHT_HASH = 5, // Symbol hash table. 1253 | SHT_DYNAMIC = 6, // Information for dynamic linking. 1254 | SHT_NOTE = 7, // Information about the file. 1255 | SHT_NOBITS = 8, // Data occupies no space in the file. 1256 | SHT_REL = 9, // Relocation entries; no explicit addends. 1257 | SHT_SHLIB = 10, // Reserved. 1258 | SHT_DYNSYM = 11, // Symbol table. 1259 | SHT_INIT_ARRAY = 14, // Pointers to initialization functions. 1260 | SHT_FINI_ARRAY = 15, // Pointers to termination functions. 1261 | SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. 1262 | SHT_GROUP = 17, // Section group. 1263 | SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. 1264 | SHT_LOOS = 0x60000000, // Lowest operating system-specific type. 1265 | SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. 1266 | SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. 1267 | SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. 1268 | SHT_GNU_verneed = 0x6ffffffe, // GNU version references. 1269 | SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. 1270 | SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. 1271 | SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. 1272 | // Fixme: All this is duplicated in MCSectionELF. Why?? 1273 | // Exception Index table 1274 | SHT_ARM_EXIDX = 0x70000001U, 1275 | // BPABI DLL dynamic linking pre-emption map 1276 | SHT_ARM_PREEMPTMAP = 0x70000002U, 1277 | // Object file compatibility attributes 1278 | SHT_ARM_ATTRIBUTES = 0x70000003U, 1279 | SHT_ARM_DEBUGOVERLAY = 0x70000004U, 1280 | SHT_ARM_OVERLAYSECTION = 0x70000005U, 1281 | SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in 1282 | // this section based on their sizes 1283 | SHT_X86_64_UNWIND = 0x70000001, // Unwind information 1284 | 1285 | SHT_MIPS_REGINFO = 0x70000006, // Register usage information 1286 | SHT_MIPS_OPTIONS = 0x7000000d, // General options 1287 | SHT_MIPS_ABIFLAGS = 0x7000002a, // Abiflags options 1288 | 1289 | SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. 1290 | SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. 1291 | SHT_HIUSER = 0xffffffff // Highest type reserved for applications. 1292 | }; 1293 | 1294 | // Section flags. 1295 | enum : unsigned { 1296 | // Section data should be writable during execution. 1297 | SHF_WRITE = 0x1, 1298 | 1299 | // Section occupies memory during program execution. 1300 | SHF_ALLOC = 0x2, 1301 | 1302 | // Section contains executable machine instructions. 1303 | SHF_EXECINSTR = 0x4, 1304 | 1305 | // The data in this section may be merged. 1306 | SHF_MERGE = 0x10, 1307 | 1308 | // The data in this section is null-terminated strings. 1309 | SHF_STRINGS = 0x20, 1310 | 1311 | // A field in this section holds a section header table index. 1312 | SHF_INFO_LINK = 0x40U, 1313 | 1314 | // Adds special ordering requirements for link editors. 1315 | SHF_LINK_ORDER = 0x80U, 1316 | 1317 | // This section requires special OS-specific processing to avoid incorrect 1318 | // behavior. 1319 | SHF_OS_NONCONFORMING = 0x100U, 1320 | 1321 | // This section is a member of a section group. 1322 | SHF_GROUP = 0x200U, 1323 | 1324 | // This section holds Thread-Local Storage. 1325 | SHF_TLS = 0x400U, 1326 | 1327 | // This section is excluded from the final executable or shared library. 1328 | SHF_EXCLUDE = 0x80000000U, 1329 | 1330 | // Start of target-specific flags. 1331 | 1332 | /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped 1333 | /// together by the linker to form the constant pool and the cp register is 1334 | /// set to the start of the constant pool by the boot code. 1335 | XCORE_SHF_CP_SECTION = 0x800U, 1336 | 1337 | /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped 1338 | /// together by the linker to form the data section and the dp register is 1339 | /// set to the start of the section by the boot code. 1340 | XCORE_SHF_DP_SECTION = 0x1000U, 1341 | 1342 | SHF_MASKOS = 0x0ff00000, 1343 | 1344 | // Bits indicating processor-specific flags. 1345 | SHF_MASKPROC = 0xf0000000, 1346 | 1347 | // If an object file section does not have this flag set, then it may not hold 1348 | // more than 2GB and can be freely referred to in objects using smaller code 1349 | // models. Otherwise, only objects using larger code models can refer to them. 1350 | // For example, a medium code model object can refer to data in a section that 1351 | // sets this flag besides being able to refer to data in a section that does 1352 | // not set it; likewise, a small code model object can refer only to code in a 1353 | // section that does not set this flag. 1354 | SHF_X86_64_LARGE = 0x10000000, 1355 | 1356 | // All sections with the GPREL flag are grouped into a global data area 1357 | // for faster accesses 1358 | SHF_HEX_GPREL = 0x10000000, 1359 | 1360 | // Section contains text/data which may be replicated in other sections. 1361 | // Linker must retain only one copy. 1362 | SHF_MIPS_NODUPES = 0x01000000, 1363 | 1364 | // Linker must generate implicit hidden weak names. 1365 | SHF_MIPS_NAMES = 0x02000000, 1366 | 1367 | // Section data local to process. 1368 | SHF_MIPS_LOCAL = 0x04000000, 1369 | 1370 | // Do not strip this section. 1371 | SHF_MIPS_NOSTRIP = 0x08000000, 1372 | 1373 | // Section must be part of global data area. 1374 | SHF_MIPS_GPREL = 0x10000000, 1375 | 1376 | // This section should be merged. 1377 | SHF_MIPS_MERGE = 0x20000000, 1378 | 1379 | // Address size to be inferred from section entry size. 1380 | SHF_MIPS_ADDR = 0x40000000, 1381 | 1382 | // Section data is string data by default. 1383 | SHF_MIPS_STRING = 0x80000000 1384 | }; 1385 | 1386 | // Section Group Flags 1387 | enum : unsigned { 1388 | GRP_COMDAT = 0x1, 1389 | GRP_MASKOS = 0x0ff00000, 1390 | GRP_MASKPROC = 0xf0000000 1391 | }; 1392 | 1393 | // Symbol table entries for ELF32. 1394 | struct Elf32_Sym { 1395 | Elf32_Word st_name; // Symbol name (index into string table) 1396 | Elf32_Addr st_value; // Value or address associated with the symbol 1397 | Elf32_Word st_size; // Size of the symbol 1398 | unsigned char st_info; // Symbol's type and binding attributes 1399 | unsigned char st_other; // Must be zero; reserved 1400 | Elf32_Half st_shndx; // Which section (header table index) it's defined in 1401 | 1402 | // These accessors and mutators correspond to the ELF32_ST_BIND, 1403 | // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: 1404 | unsigned char getBinding() const { return st_info >> 4; } 1405 | unsigned char getType() const { return st_info & 0x0f; } 1406 | void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 1407 | void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 1408 | void setBindingAndType(unsigned char b, unsigned char t) { 1409 | st_info = (b << 4) + (t & 0x0f); 1410 | } 1411 | }; 1412 | 1413 | // BEGIN android-added for compat 1414 | static inline unsigned char ELF32_ST_TYPE(unsigned char st_info) { return st_info & 0x0f; } 1415 | static inline unsigned char ELF64_ST_TYPE(unsigned char st_info) { return st_info & 0x0f; } 1416 | // END android-added for compat 1417 | 1418 | // Symbol table entries for ELF64. 1419 | struct Elf64_Sym { 1420 | Elf64_Word st_name; // Symbol name (index into string table) 1421 | unsigned char st_info; // Symbol's type and binding attributes 1422 | unsigned char st_other; // Must be zero; reserved 1423 | Elf64_Half st_shndx; // Which section (header tbl index) it's defined in 1424 | Elf64_Addr st_value; // Value or address associated with the symbol 1425 | Elf64_Xword st_size; // Size of the symbol 1426 | 1427 | // These accessors and mutators are identical to those defined for ELF32 1428 | // symbol table entries. 1429 | unsigned char getBinding() const { return st_info >> 4; } 1430 | unsigned char getType() const { return st_info & 0x0f; } 1431 | void setBinding(unsigned char b) { setBindingAndType(b, getType()); } 1432 | void setType(unsigned char t) { setBindingAndType(getBinding(), t); } 1433 | void setBindingAndType(unsigned char b, unsigned char t) { 1434 | st_info = (b << 4) + (t & 0x0f); 1435 | } 1436 | }; 1437 | 1438 | // The size (in bytes) of symbol table entries. 1439 | enum { 1440 | SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size 1441 | SYMENTRY_SIZE64 = 24 // 64-bit symbol entry size. 1442 | }; 1443 | 1444 | // Symbol bindings. 1445 | enum { 1446 | STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def 1447 | STB_GLOBAL = 1, // Global symbol, visible to all object files being combined 1448 | STB_WEAK = 2, // Weak symbol, like global but lower-precedence 1449 | STB_LOOS = 10, // Lowest operating system-specific binding type 1450 | STB_HIOS = 12, // Highest operating system-specific binding type 1451 | STB_LOPROC = 13, // Lowest processor-specific binding type 1452 | STB_HIPROC = 15 // Highest processor-specific binding type 1453 | }; 1454 | 1455 | // Symbol types. 1456 | enum { 1457 | STT_NOTYPE = 0, // Symbol's type is not specified 1458 | STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) 1459 | STT_FUNC = 2, // Symbol is executable code (function, etc.) 1460 | STT_SECTION = 3, // Symbol refers to a section 1461 | STT_FILE = 4, // Local, absolute symbol that refers to a file 1462 | STT_COMMON = 5, // An uninitialized common block 1463 | STT_TLS = 6, // Thread local data object 1464 | STT_LOOS = 7, // Lowest operating system-specific symbol type 1465 | STT_HIOS = 8, // Highest operating system-specific symbol type 1466 | STT_GNU_IFUNC = 10, // GNU indirect function 1467 | STT_LOPROC = 13, // Lowest processor-specific symbol type 1468 | STT_HIPROC = 15 // Highest processor-specific symbol type 1469 | }; 1470 | 1471 | enum { 1472 | STV_DEFAULT = 0, // Visibility is specified by binding type 1473 | STV_INTERNAL = 1, // Defined by processor supplements 1474 | STV_HIDDEN = 2, // Not visible to other components 1475 | STV_PROTECTED = 3 // Visible in other components but not preemptable 1476 | }; 1477 | 1478 | // Symbol number. 1479 | enum { 1480 | STN_UNDEF = 0 1481 | }; 1482 | 1483 | // Relocation entry, without explicit addend. 1484 | struct Elf32_Rel { 1485 | Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) 1486 | Elf32_Word r_info; // Symbol table index and type of relocation to apply 1487 | 1488 | // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, 1489 | // and ELF32_R_INFO macros defined in the ELF specification: 1490 | Elf32_Word getSymbol() const { return (r_info >> 8); } 1491 | unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } 1492 | void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } 1493 | void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 1494 | void setSymbolAndType(Elf32_Word s, unsigned char t) { 1495 | r_info = (s << 8) + t; 1496 | } 1497 | }; 1498 | 1499 | // Relocation entry with explicit addend. 1500 | struct Elf32_Rela { 1501 | Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) 1502 | Elf32_Word r_info; // Symbol table index and type of relocation to apply 1503 | Elf32_Sword r_addend; // Compute value for relocatable field by adding this 1504 | 1505 | // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, 1506 | // and ELF32_R_INFO macros defined in the ELF specification: 1507 | Elf32_Word getSymbol() const { return (r_info >> 8); } 1508 | unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } 1509 | void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } 1510 | void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } 1511 | void setSymbolAndType(Elf32_Word s, unsigned char t) { 1512 | r_info = (s << 8) + t; 1513 | } 1514 | }; 1515 | 1516 | // Relocation entry, without explicit addend. 1517 | struct Elf64_Rel { 1518 | Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). 1519 | Elf64_Xword r_info; // Symbol table index and type of relocation to apply. 1520 | 1521 | // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, 1522 | // and ELF64_R_INFO macros defined in the ELF specification: 1523 | Elf64_Word getSymbol() const { return (r_info >> 32); } 1524 | Elf64_Word getType() const { 1525 | return (Elf64_Word) (r_info & 0xffffffffL); 1526 | } 1527 | void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } 1528 | void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } 1529 | void setSymbolAndType(Elf64_Word s, Elf64_Word t) { 1530 | r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); 1531 | } 1532 | }; 1533 | 1534 | // Relocation entry with explicit addend. 1535 | struct Elf64_Rela { 1536 | Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). 1537 | Elf64_Xword r_info; // Symbol table index and type of relocation to apply. 1538 | Elf64_Sxword r_addend; // Compute value for relocatable field by adding this. 1539 | 1540 | // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, 1541 | // and ELF64_R_INFO macros defined in the ELF specification: 1542 | Elf64_Word getSymbol() const { return (r_info >> 32); } 1543 | Elf64_Word getType() const { 1544 | return (Elf64_Word) (r_info & 0xffffffffL); 1545 | } 1546 | void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } 1547 | void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } 1548 | void setSymbolAndType(Elf64_Word s, Elf64_Word t) { 1549 | r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); 1550 | } 1551 | }; 1552 | 1553 | // Program header for ELF32. 1554 | struct Elf32_Phdr { 1555 | Elf32_Word p_type; // Type of segment 1556 | Elf32_Off p_offset; // File offset where segment is located, in bytes 1557 | Elf32_Addr p_vaddr; // Virtual address of beginning of segment 1558 | Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) 1559 | Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) 1560 | Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) 1561 | Elf32_Word p_flags; // Segment flags 1562 | Elf32_Word p_align; // Segment alignment constraint 1563 | }; 1564 | 1565 | // Program header for ELF64. 1566 | struct Elf64_Phdr { 1567 | Elf64_Word p_type; // Type of segment 1568 | Elf64_Word p_flags; // Segment flags 1569 | Elf64_Off p_offset; // File offset where segment is located, in bytes 1570 | Elf64_Addr p_vaddr; // Virtual address of beginning of segment 1571 | Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) 1572 | Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) 1573 | Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) 1574 | Elf64_Xword p_align; // Segment alignment constraint 1575 | }; 1576 | 1577 | // Segment types. 1578 | enum { 1579 | PT_NULL = 0, // Unused segment. 1580 | PT_LOAD = 1, // Loadable segment. 1581 | PT_DYNAMIC = 2, // Dynamic linking information. 1582 | PT_INTERP = 3, // Interpreter pathname. 1583 | PT_NOTE = 4, // Auxiliary information. 1584 | PT_SHLIB = 5, // Reserved. 1585 | PT_PHDR = 6, // The program header table itself. 1586 | PT_TLS = 7, // The thread-local storage template. 1587 | PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. 1588 | PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. 1589 | PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. 1590 | PT_HIPROC = 0x7fffffff, // Highest processor-specific program hdr entry type. 1591 | 1592 | // x86-64 program header types. 1593 | // These all contain stack unwind tables. 1594 | PT_GNU_EH_FRAME = 0x6474e550, 1595 | PT_SUNW_EH_FRAME = 0x6474e550, 1596 | PT_SUNW_UNWIND = 0x6464e550, 1597 | 1598 | PT_GNU_STACK = 0x6474e551, // Indicates stack executability. 1599 | PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. 1600 | 1601 | // ARM program header types. 1602 | PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info 1603 | // These all contain stack unwind tables. 1604 | PT_ARM_EXIDX = 0x70000001, 1605 | PT_ARM_UNWIND = 0x70000001, 1606 | 1607 | // MIPS program header types. 1608 | PT_MIPS_REGINFO = 0x70000000, // Register usage information. 1609 | PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. 1610 | PT_MIPS_OPTIONS = 0x70000002, // Options segment. 1611 | PT_MIPS_ABIFLAGS = 0x70000003 // Abiflags segment. 1612 | }; 1613 | 1614 | // Segment flag bits. 1615 | enum : unsigned { 1616 | PF_X = 1, // Execute 1617 | PF_W = 2, // Write 1618 | PF_R = 4, // Read 1619 | PF_MASKOS = 0x0ff00000,// Bits for operating system-specific semantics. 1620 | PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics. 1621 | }; 1622 | 1623 | // Dynamic table entry for ELF32. 1624 | struct Elf32_Dyn 1625 | { 1626 | Elf32_Sword d_tag; // Type of dynamic table entry. 1627 | union 1628 | { 1629 | Elf32_Word d_val; // Integer value of entry. 1630 | Elf32_Addr d_ptr; // Pointer value of entry. 1631 | } d_un; 1632 | }; 1633 | 1634 | // Dynamic table entry for ELF64. 1635 | struct Elf64_Dyn 1636 | { 1637 | Elf64_Sxword d_tag; // Type of dynamic table entry. 1638 | union 1639 | { 1640 | Elf64_Xword d_val; // Integer value of entry. 1641 | Elf64_Addr d_ptr; // Pointer value of entry. 1642 | } d_un; 1643 | }; 1644 | 1645 | // Dynamic table entry tags. 1646 | enum { 1647 | DT_NULL = 0, // Marks end of dynamic array. 1648 | DT_NEEDED = 1, // String table offset of needed library. 1649 | DT_PLTRELSZ = 2, // Size of relocation entries in PLT. 1650 | DT_PLTGOT = 3, // Address associated with linkage table. 1651 | DT_HASH = 4, // Address of symbolic hash table. 1652 | DT_STRTAB = 5, // Address of dynamic string table. 1653 | DT_SYMTAB = 6, // Address of dynamic symbol table. 1654 | DT_RELA = 7, // Address of relocation table (Rela entries). 1655 | DT_RELASZ = 8, // Size of Rela relocation table. 1656 | DT_RELAENT = 9, // Size of a Rela relocation entry. 1657 | DT_STRSZ = 10, // Total size of the string table. 1658 | DT_SYMENT = 11, // Size of a symbol table entry. 1659 | DT_INIT = 12, // Address of initialization function. 1660 | DT_FINI = 13, // Address of termination function. 1661 | DT_SONAME = 14, // String table offset of a shared objects name. 1662 | DT_RPATH = 15, // String table offset of library search path. 1663 | DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. 1664 | DT_REL = 17, // Address of relocation table (Rel entries). 1665 | DT_RELSZ = 18, // Size of Rel relocation table. 1666 | DT_RELENT = 19, // Size of a Rel relocation entry. 1667 | DT_PLTREL = 20, // Type of relocation entry used for linking. 1668 | DT_DEBUG = 21, // Reserved for debugger. 1669 | DT_TEXTREL = 22, // Relocations exist for non-writable segments. 1670 | DT_JMPREL = 23, // Address of relocations associated with PLT. 1671 | DT_BIND_NOW = 24, // Process all relocations before execution. 1672 | DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. 1673 | DT_FINI_ARRAY = 26, // Pointer to array of termination functions. 1674 | DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. 1675 | DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. 1676 | DT_RUNPATH = 29, // String table offset of lib search path. 1677 | DT_FLAGS = 30, // Flags. 1678 | DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules 1679 | // for the interpretation of the d_un union. 1680 | 1681 | DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. 1682 | DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. 1683 | 1684 | DT_LOOS = 0x60000000, // Start of environment specific tags. 1685 | DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. 1686 | DT_LOPROC = 0x70000000, // Start of processor specific tags. 1687 | DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. 1688 | 1689 | DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. 1690 | DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. 1691 | DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. 1692 | 1693 | DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. 1694 | DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. 1695 | DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. 1696 | DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. 1697 | DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. 1698 | DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED. 1699 | 1700 | // Mips specific dynamic table entry tags. 1701 | DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime 1702 | // linker interface. 1703 | DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp. 1704 | DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings 1705 | // and common sizes. 1706 | DT_MIPS_IVERSION = 0x70000004, // Index of version string 1707 | // in string table. 1708 | DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags. 1709 | DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment. 1710 | DT_MIPS_MSYM = 0x70000007, // Address of .msym section. 1711 | DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section. 1712 | DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section. 1713 | DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset 1714 | // table entries. 1715 | DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries 1716 | // in the .conflict section. 1717 | DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries 1718 | // in the .liblist section. 1719 | DT_MIPS_SYMTABNO = 0x70000011, // Number of entries 1720 | // in the .dynsym section. 1721 | DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol 1722 | // not referenced locally. 1723 | DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol 1724 | // in global offset table. 1725 | DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries 1726 | // in global offset table. 1727 | DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map, 1728 | // used for debugging. 1729 | DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition. 1730 | DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries 1731 | // in DT_MIPS_DELTA_CLASS. 1732 | DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances. 1733 | DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries 1734 | // in DT_MIPS_DELTA_INSTANCE. 1735 | DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations. 1736 | DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries 1737 | // in DT_MIPS_DELTA_RELOC. 1738 | DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta 1739 | // relocations refer to. 1740 | DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries 1741 | // in DT_MIPS_DELTA_SYM. 1742 | DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold 1743 | // class declarations. 1744 | DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries 1745 | // in DT_MIPS_DELTA_CLASSSYM. 1746 | DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information 1747 | // about C++ flavor. 1748 | DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information. 1749 | DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib 1750 | DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE 1751 | // for a segment 1752 | DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE 1753 | // for a local symbol 1754 | DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE 1755 | // for a hidden symbol 1756 | DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE 1757 | // for a protected symbol 1758 | DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'. 1759 | DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'. 1760 | DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown. 1761 | DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section. 1762 | DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve 1763 | // function stored in the GOT. 1764 | DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added 1765 | // by rld on dlopen() calls. 1766 | DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation 1767 | // section (O32). 1768 | DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs. 1769 | DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic. 1770 | DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. 1771 | DT_MIPS_RWPLT = 0x70000034 // Points to the base 1772 | // of a writable PLT. 1773 | }; 1774 | 1775 | // DT_FLAGS values. 1776 | enum { 1777 | DF_ORIGIN = 0x01, // The object may reference $ORIGIN. 1778 | DF_SYMBOLIC = 0x02, // Search the shared lib before searching the exe. 1779 | DF_TEXTREL = 0x04, // Relocations may modify a non-writable segment. 1780 | DF_BIND_NOW = 0x08, // Process all relocations on load. 1781 | DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. 1782 | }; 1783 | 1784 | // State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. 1785 | enum { 1786 | DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. 1787 | DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. 1788 | DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. 1789 | DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. 1790 | DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. 1791 | DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. 1792 | DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. 1793 | DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. 1794 | DF_1_DIRECT = 0x00000100, // Direct binding enabled. 1795 | DF_1_TRANS = 0x00000200, 1796 | DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. 1797 | DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. 1798 | DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. 1799 | DF_1_CONFALT = 0x00002000, // Configuration alternative created. 1800 | DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. 1801 | DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. 1802 | DF_1_DISPRELPND = 0x00010000 // Disp reloc applied at run-time. 1803 | }; 1804 | 1805 | // DT_MIPS_FLAGS values. 1806 | enum { 1807 | RHF_NONE = 0x00000000, // No flags. 1808 | RHF_QUICKSTART = 0x00000001, // Uses shortcut pointers. 1809 | RHF_NOTPOT = 0x00000002, // Hash size is not a power of two. 1810 | RHS_NO_LIBRARY_REPLACEMENT = 0x00000004, // Ignore LD_LIBRARY_PATH. 1811 | RHF_NO_MOVE = 0x00000008, // DSO address may not be relocated. 1812 | RHF_SGI_ONLY = 0x00000010, // SGI specific features. 1813 | RHF_GUARANTEE_INIT = 0x00000020, // Guarantee that .init will finish 1814 | // executing before any non-init 1815 | // code in DSO is called. 1816 | RHF_DELTA_C_PLUS_PLUS = 0x00000040, // Contains Delta C++ code. 1817 | RHF_GUARANTEE_START_INIT = 0x00000080, // Guarantee that .init will start 1818 | // executing before any non-init 1819 | // code in DSO is called. 1820 | RHF_PIXIE = 0x00000100, // Generated by pixie. 1821 | RHF_DEFAULT_DELAY_LOAD = 0x00000200, // Delay-load DSO by default. 1822 | RHF_REQUICKSTART = 0x00000400, // Object may be requickstarted 1823 | RHF_REQUICKSTARTED = 0x00000800, // Object has been requickstarted 1824 | RHF_CORD = 0x00001000, // Generated by cord. 1825 | RHF_NO_UNRES_UNDEF = 0x00002000, // Object contains no unresolved 1826 | // undef symbols. 1827 | RHF_RLD_ORDER_SAFE = 0x00004000 // Symbol table is in a safe order. 1828 | }; 1829 | 1830 | // ElfXX_VerDef structure version (GNU versioning) 1831 | enum { 1832 | VER_DEF_NONE = 0, 1833 | VER_DEF_CURRENT = 1 1834 | }; 1835 | 1836 | // VerDef Flags (ElfXX_VerDef::vd_flags) 1837 | enum { 1838 | VER_FLG_BASE = 0x1, 1839 | VER_FLG_WEAK = 0x2, 1840 | VER_FLG_INFO = 0x4 1841 | }; 1842 | 1843 | // Special constants for the version table. (SHT_GNU_versym/.gnu.version) 1844 | enum { 1845 | VER_NDX_LOCAL = 0, // Unversioned local symbol 1846 | VER_NDX_GLOBAL = 1, // Unversioned global symbol 1847 | VERSYM_VERSION = 0x7fff, // Version Index mask 1848 | VERSYM_HIDDEN = 0x8000 // Hidden bit (non-default version) 1849 | }; 1850 | 1851 | // ElfXX_VerNeed structure version (GNU versioning) 1852 | enum { 1853 | VER_NEED_NONE = 0, 1854 | VER_NEED_CURRENT = 1 1855 | }; 1856 | 1857 | struct ElfTypes32 { 1858 | typedef Elf32_Addr Addr; 1859 | typedef Elf32_Off Off; 1860 | typedef Elf32_Half Half; 1861 | typedef Elf32_Word Word; 1862 | typedef Elf32_Sword Sword; 1863 | typedef Elf32_Ehdr Ehdr; 1864 | typedef Elf32_Shdr Shdr; 1865 | typedef Elf32_Sym Sym; 1866 | typedef Elf32_Rel Rel; 1867 | typedef Elf32_Rela Rela; 1868 | typedef Elf32_Phdr Phdr; 1869 | typedef Elf32_Dyn Dyn; 1870 | }; 1871 | 1872 | struct ElfTypes64 { 1873 | typedef Elf64_Addr Addr; 1874 | typedef Elf64_Off Off; 1875 | typedef Elf64_Half Half; 1876 | typedef Elf64_Word Word; 1877 | typedef Elf64_Sword Sword; 1878 | typedef Elf64_Xword Xword; 1879 | typedef Elf64_Sxword Sxword; 1880 | typedef Elf64_Ehdr Ehdr; 1881 | typedef Elf64_Shdr Shdr; 1882 | typedef Elf64_Sym Sym; 1883 | typedef Elf64_Rel Rel; 1884 | typedef Elf64_Rela Rela; 1885 | typedef Elf64_Phdr Phdr; 1886 | typedef Elf64_Dyn Dyn; 1887 | }; 1888 | 1889 | // BEGIN android-changed 1890 | #endif // ART_RUNTIME_ELF_H_ 1891 | // END android-changed 1892 | -------------------------------------------------------------------------------- /src/exutil.h: -------------------------------------------------------------------------------- 1 | #ifndef _SO_REBUILDER_EXUTIL_H_ 2 | #define _SO_REBUILDER_EXUTIL_H_ 3 | 4 | #include "elf.h" 5 | //check the environment and define the necessery type 6 | #ifndef __LP64__ 7 | typedef Elf32_Addr Elf_Addr; 8 | typedef Elf32_Dyn Elf_Dyn; 9 | typedef Elf32_Ehdr Elf_Ehdr; 10 | typedef Elf32_Half Elf_Half; 11 | typedef Elf32_Off Elf_Off; 12 | typedef Elf32_Phdr Elf_Phdr; 13 | typedef Elf32_Rel Elf_Rel; 14 | typedef Elf32_Rela Elf_Rela; 15 | typedef Elf32_Shdr Elf_Shdr; 16 | typedef Elf32_Sword Elf_Sword; 17 | typedef Elf32_Sym Elf_Sym; 18 | typedef Elf32_Word Elf_Word; 19 | #else 20 | // Because we handle with 32bits ELF file. 21 | // In 32bits Elf file, the header size, section size, etc, 22 | // should use 32 bit type, or it will read out range of header. 23 | typedef Elf64_Addr Elf_Addr; 24 | typedef Elf32_Dyn Elf_Dyn; 25 | typedef Elf32_Ehdr Elf_Ehdr; 26 | typedef Elf64_Half Elf_Half; 27 | typedef Elf64_Off Elf_Off; 28 | typedef Elf32_Phdr Elf_Phdr; 29 | typedef Elf32_Rel Elf_Rel; 30 | typedef Elf32_Rela Elf_Rela; 31 | typedef Elf32_Shdr Elf_Shdr; 32 | typedef Elf64_Sword Elf_Sword; 33 | typedef Elf32_Sym Elf_Sym; 34 | typedef Elf64_Word Elf_Word; 35 | #endif 36 | 37 | 38 | #ifndef PAGE_SIZE 39 | #define PAGE_SIZE 0x1000 40 | #endif 41 | 42 | #define PAGE_MASK (~(PAGE_SIZE-1)) 43 | // Returns the address of the page containing address 'x'. 44 | #define PAGE_START(x) ((x) & PAGE_MASK) 45 | 46 | // Returns the offset of address 'x' in its page. 47 | #define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) 48 | 49 | // Returns the address of the next page after address 'x', unless 'x' is 50 | // itself at the start of a page. 51 | #define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) 52 | 53 | #endif -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Log.h" 6 | #include "ELFReader.h" 7 | #include "ELFRebuilder.h" 8 | 9 | void usage(){ 10 | std::cout<<"So Rebuilder --Powered by giglf\n" 11 | <<"usage: sb \n" 12 | <<" sb -o \n" 13 | <<"\n" 14 | <<"option: \n" 15 | <<" -o --output Specify the output file name. Or append \"_repaired\" default.\n" 16 | <<" -c --check Check the damage level and print it.\n" 17 | <<" -f --force Force to fully rebuild the section.\n" 18 | <<" -m --memso Source file is dump from memory from address x(hex)\n" 19 | <<" -v --verbose Print the verbose repair information\n" 20 | <<" -h --help Print this usage.\n" 21 | <<" -d --debug Print this program debug log." 22 | <GetJavaVM(); 105 | bool success = vm->LoadNativeLibrary(env, 106 | filename.c_str(), 107 | javaLoader, 108 | javaLibrarySearchPath, 109 | &error_msg); 110 | if (success) { 111 | return nullptr; 112 | } 113 | } 114 | 115 | // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF. 116 | env->ExceptionClear(); 117 | return env->NewStringUTF(error_msg.c_str()); 118 | } 119 | ``` 120 | 121 | 经过一系列的跳转,终于跑到关键的函数了 122 | 123 | 这个函数太长,不便于看思路,所以我只保留下了一些关键的代码 124 | 125 | ```cpp 126 | // ./art/runtime/java_vm_ext.cc 127 | 128 | bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, 129 | const std::string& path, 130 | jobject class_loader, 131 | jstring library_path, 132 | std::string* error_msg) { 133 | 134 | //检查该NativeLibrary是否已加载 135 | ...... 136 | 137 | // Open the shared library. Because we're using a full path, the system 138 | // doesn't have to search through LD_LIBRARY_PATH. (It may do so to 139 | // resolve this library's dependencies though.) 140 | 141 | // Failures here are expected when java.library.path has several entries 142 | // and we have to hunt for the lib. 143 | 144 | // Below we dlopen but there is no paired dlclose, this would be necessary if we supported 145 | // class unloading. Libraries will only be unloaded when the reference count (incremented by 146 | // dlopen) becomes zero from dlclose. 147 | 148 | Locks::mutator_lock_->AssertNotHeld(self); 149 | const char* path_str = path.empty() ? nullptr : path.c_str(); 150 | void* handle = android::OpenNativeLibrary(env, 151 | runtime_->GetTargetSdkVersion(), 152 | path_str, 153 | class_loader, 154 | library_path); 155 | 156 | bool needs_native_bridge = false; 157 | if (handle == nullptr) { 158 | if (android::NativeBridgeIsSupported(path_str)) { 159 | handle = android::NativeBridgeLoadLibrary(path_str, RTLD_NOW); 160 | needs_native_bridge = true; 161 | } 162 | } 163 | 164 | VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_NOW) returned " << handle << "]"; 165 | 166 | if (handle == nullptr) { 167 | *error_msg = dlerror(); 168 | VLOG(jni) << "dlopen(\"" << path << "\", RTLD_NOW) failed: " << *error_msg; 169 | return false; 170 | } 171 | 172 | ...... 173 | 174 | VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]"; 175 | ...... 176 | bool was_successful = false; 177 | void* sym; 178 | if (needs_native_bridge) { 179 | library->SetNeedsNativeBridge(); 180 | } 181 | sym = library->FindSymbol("JNI_OnLoad", nullptr); 182 | if (sym == nullptr) { 183 | VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]"; 184 | was_successful = true; 185 | } else { 186 | // Call JNI_OnLoad. We have to override the current class 187 | // loader, which will always be "null" since the stuff at the 188 | // top of the stack is around Runtime.loadLibrary(). (See 189 | // the comments in the JNI FindClass function.) 190 | ScopedLocalRef old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride())); 191 | self->SetClassLoaderOverride(class_loader); 192 | 193 | VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]"; 194 | typedef int (*JNI_OnLoadFn)(JavaVM*, void*); 195 | JNI_OnLoadFn jni_on_load = reinterpret_cast(sym); 196 | int version = (*jni_on_load)(this, nullptr); 197 | 198 | if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) { 199 | fault_manager.EnsureArtActionInFrontOfSignalChain(); 200 | } 201 | 202 | self->SetClassLoaderOverride(old_class_loader.get()); 203 | 204 | ...... 205 | //Version check 206 | VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure") 207 | << " from JNI_OnLoad in \"" << path << "\"]"; 208 | } 209 | 210 | library->SetResult(was_successful); 211 | return was_successful; 212 | } 213 | ``` 214 | 215 | 排除去一些版本检测,一些操作的语句,其实这个函数做的就是两个步骤 216 | 217 | 1. 调用`android::OpenNativeLibrary`,动态加载so到内存 218 | 2. 从so中找到`JNI_Onload`函数,并调用。`sym = library->FindSymbol("JNI_OnLoad", nullptr);` 219 | 220 | --- 221 | 222 | 然后我们再找到`android::OpenNativeLibrary`的源码 223 | 224 | ```cpp 225 | //./system/core/libnativeloader/include/nativeloader/native_loader.cpp 226 | 227 | void* OpenNativeLibrary(JNIEnv* env, 228 | int32_t target_sdk_version, 229 | const char* path, 230 | jobject class_loader, 231 | jstring library_path) { 232 | #if defined(__ANDROID__) 233 | UNUSED(target_sdk_version); 234 | if (class_loader == nullptr) { 235 | return dlopen(path, RTLD_NOW); 236 | } 237 | 238 | std::lock_guard guard(g_namespaces_mutex); 239 | android_namespace_t* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader); 240 | 241 | if (ns == nullptr) { 242 | // This is the case where the classloader was not created by ApplicationLoaders 243 | // In this case we create an isolated not-shared namespace for it. 244 | ns = g_namespaces->Create(env, class_loader, false, library_path, nullptr); 245 | if (ns == nullptr) { 246 | return nullptr; 247 | } 248 | } 249 | 250 | android_dlextinfo extinfo; 251 | extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 252 | extinfo.library_namespace = ns; 253 | 254 | return android_dlopen_ext(path, RTLD_NOW, &extinfo); 255 | #else 256 | UNUSED(env, target_sdk_version, class_loader, library_path); 257 | return dlopen(path, RTLD_NOW); 258 | #endif 259 | } 260 | ``` 261 | 262 | 思路也很简单,这里就是调用了`dlopen` 263 | 264 | 然后后面对应还有`dlclose` `dlsym` `dlerror`等对应 programming interface to dynamic linking loader 265 | 266 | 这些函数位于 267 | 268 | `./bionic/linker/dlfcn.cpp` 269 | 270 | 具体实现位于 271 | 272 | `./bionic/linker/linker.cpp` 273 | 274 | ```cpp 275 | //./bionic/linker/linker.cpp 276 | void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, 277 | void* caller_addr) { 278 | soinfo* const caller = find_containing_library(caller_addr); 279 | 280 | if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) { 281 | DL_ERR("invalid flags to dlopen: %x", flags); 282 | return nullptr; 283 | } 284 | 285 | android_namespace_t* ns = get_caller_namespace(caller); 286 | 287 | //一些flag的设置和检查 288 | ...... 289 | 290 | std::string asan_name_holder; 291 | 292 | const char* translated_name = name; 293 | if (g_is_asan) { 294 | if (file_is_in_dir(name, kSystemLibDir)) { 295 | asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(name); 296 | if (file_exists(asan_name_holder.c_str())) { 297 | translated_name = asan_name_holder.c_str(); 298 | PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name); 299 | } 300 | } else if (file_is_in_dir(name, kVendorLibDir)) { 301 | asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(name); 302 | if (file_exists(asan_name_holder.c_str())) { 303 | translated_name = asan_name_holder.c_str(); 304 | PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name); 305 | } 306 | } 307 | } 308 | 309 | ProtectedDataGuard guard; 310 | soinfo* si = find_library(ns, translated_name, flags, extinfo, caller); 311 | if (si != nullptr) { 312 | si->call_constructors(); 313 | return si->to_handle(); 314 | } 315 | 316 | return nullptr; 317 | } 318 | ``` 319 | 320 | 这里主要关注一个关键的结构体`soinfo` 321 | 322 | 这个结构体储存了so在加载后的信息 323 | 324 | 其定义在`./bionic/linker/linker.h` 325 | 326 | ```cpp 327 | struct soinfo { 328 | public: 329 | typedef LinkedList soinfo_list_t; 330 | typedef LinkedList android_namespace_list_t; 331 | #if defined(__work_around_b_24465209__) 332 | private: 333 | char old_name_[SOINFO_NAME_LEN]; 334 | #endif 335 | public: 336 | const ElfW(Phdr)* phdr; 337 | size_t phnum; 338 | ElfW(Addr) entry; 339 | ElfW(Addr) base; 340 | size_t size; 341 | 342 | #if defined(__work_around_b_24465209__) 343 | uint32_t unused1; // DO NOT USE, maintained for compatibility. 344 | #endif 345 | 346 | ElfW(Dyn)* dynamic; 347 | 348 | #if defined(__work_around_b_24465209__) 349 | uint32_t unused2; // DO NOT USE, maintained for compatibility 350 | uint32_t unused3; // DO NOT USE, maintained for compatibility 351 | #endif 352 | 353 | soinfo* next; 354 | private: 355 | uint32_t flags_; 356 | 357 | const char* strtab_; 358 | ElfW(Sym)* symtab_; 359 | 360 | size_t nbucket_; 361 | size_t nchain_; 362 | uint32_t* bucket_; 363 | uint32_t* chain_; 364 | 365 | #if defined(__mips__) || !defined(__LP64__) 366 | // This is only used by mips and mips64, but needs to be here for 367 | // all 32-bit architectures to preserve binary compatibility. 368 | ElfW(Addr)** plt_got_; 369 | #endif 370 | 371 | #if defined(USE_RELA) 372 | ElfW(Rela)* plt_rela_; 373 | size_t plt_rela_count_; 374 | 375 | ElfW(Rela)* rela_; 376 | size_t rela_count_; 377 | #else 378 | ElfW(Rel)* plt_rel_; 379 | size_t plt_rel_count_; 380 | 381 | ElfW(Rel)* rel_; 382 | size_t rel_count_; 383 | #endif 384 | 385 | linker_function_t* preinit_array_; 386 | size_t preinit_array_count_; 387 | 388 | linker_function_t* init_array_; 389 | size_t init_array_count_; 390 | linker_function_t* fini_array_; 391 | size_t fini_array_count_; 392 | 393 | linker_function_t init_func_; 394 | linker_function_t fini_func_; 395 | 396 | #if defined(__arm__) 397 | public: 398 | // ARM EABI section used for stack unwinding. 399 | uint32_t* ARM_exidx; 400 | size_t ARM_exidx_count; 401 | private: 402 | #elif defined(__mips__) 403 | uint32_t mips_symtabno_; 404 | uint32_t mips_local_gotno_; 405 | uint32_t mips_gotsym_; 406 | bool mips_relocate_got(const VersionTracker& version_tracker, 407 | const soinfo_list_t& global_group, 408 | const soinfo_list_t& local_group); 409 | #if !defined(__LP64__) 410 | bool mips_check_and_adjust_fp_modes(); 411 | #endif 412 | #endif 413 | size_t ref_count_; 414 | public: 415 | link_map link_map_head; 416 | 417 | bool constructors_called; 418 | 419 | // When you read a virtual address from the ELF file, add this 420 | // value to get the corresponding address in the process' address space. 421 | ElfW(Addr) load_bias; 422 | 423 | #if !defined(__LP64__) 424 | bool has_text_relocations; 425 | #endif 426 | bool has_DT_SYMBOLIC; 427 | 428 | public: 429 | soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat, 430 | off64_t file_offset, int rtld_flags); 431 | ~soinfo(); 432 | 433 | void call_constructors(); 434 | void call_destructors(); 435 | void call_pre_init_constructors(); 436 | bool prelink_image(); 437 | bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, 438 | const android_dlextinfo* extinfo); 439 | bool protect_relro(); 440 | 441 | void add_child(soinfo* child); 442 | void remove_all_links(); 443 | 444 | ino_t get_st_ino() const; 445 | dev_t get_st_dev() const; 446 | off64_t get_file_offset() const; 447 | 448 | uint32_t get_rtld_flags() const; 449 | uint32_t get_dt_flags_1() const; 450 | void set_dt_flags_1(uint32_t dt_flags_1); 451 | 452 | soinfo_list_t& get_children(); 453 | const soinfo_list_t& get_children() const; 454 | 455 | soinfo_list_t& get_parents(); 456 | 457 | bool find_symbol_by_name(SymbolName& symbol_name, 458 | const version_info* vi, 459 | const ElfW(Sym)** symbol) const; 460 | 461 | ElfW(Sym)* find_symbol_by_address(const void* addr); 462 | ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const; 463 | 464 | const char* get_string(ElfW(Word) index) const; 465 | bool can_unload() const; 466 | bool is_gnu_hash() const; 467 | 468 | bool inline has_min_version(uint32_t min_version __unused) const { 469 | #if defined(__work_around_b_24465209__) 470 | return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version; 471 | #else 472 | return true; 473 | #endif 474 | } 475 | 476 | bool is_linked() const; 477 | bool is_linker() const; 478 | bool is_main_executable() const; 479 | 480 | void set_linked(); 481 | void set_linker_flag(); 482 | void set_main_executable(); 483 | void set_nodelete(); 484 | 485 | void increment_ref_count(); 486 | size_t decrement_ref_count(); 487 | 488 | soinfo* get_local_group_root() const; 489 | 490 | void set_soname(const char* soname); 491 | const char* get_soname() const; 492 | const char* get_realpath() const; 493 | const ElfW(Versym)* get_versym(size_t n) const; 494 | ElfW(Addr) get_verneed_ptr() const; 495 | size_t get_verneed_cnt() const; 496 | ElfW(Addr) get_verdef_ptr() const; 497 | size_t get_verdef_cnt() const; 498 | 499 | bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const; 500 | 501 | uint32_t get_target_sdk_version() const; 502 | 503 | void set_dt_runpath(const char *); 504 | const std::vector& get_dt_runpath() const; 505 | android_namespace_t* get_primary_namespace(); 506 | void add_secondary_namespace(android_namespace_t* secondary_ns); 507 | 508 | void set_mapped_by_caller(bool reserved_map); 509 | bool is_mapped_by_caller() const; 510 | 511 | uintptr_t get_handle() const; 512 | void generate_handle(); 513 | void* to_handle(); 514 | 515 | private: 516 | bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const; 517 | ElfW(Sym)* elf_addr_lookup(const void* addr); 518 | bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const; 519 | ElfW(Sym)* gnu_addr_lookup(const void* addr); 520 | 521 | bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym, 522 | const char* sym_name, const version_info** vi); 523 | 524 | void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse); 525 | void call_function(const char* function_name, linker_function_t function); 526 | template 527 | bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator, 528 | const soinfo_list_t& global_group, const soinfo_list_t& local_group); 529 | 530 | private: 531 | // This part of the structure is only available 532 | // when FLAG_NEW_SOINFO is set in this->flags. 533 | uint32_t version_; 534 | 535 | // version >= 0 536 | dev_t st_dev_; 537 | ino_t st_ino_; 538 | 539 | // dependency graph 540 | soinfo_list_t children_; 541 | soinfo_list_t parents_; 542 | 543 | // version >= 1 544 | off64_t file_offset_; 545 | uint32_t rtld_flags_; 546 | uint32_t dt_flags_1_; 547 | size_t strtab_size_; 548 | 549 | // version >= 2 550 | 551 | size_t gnu_nbucket_; 552 | uint32_t* gnu_bucket_; 553 | uint32_t* gnu_chain_; 554 | uint32_t gnu_maskwords_; 555 | uint32_t gnu_shift2_; 556 | ElfW(Addr)* gnu_bloom_filter_; 557 | 558 | soinfo* local_group_root_; 559 | 560 | uint8_t* android_relocs_; 561 | size_t android_relocs_size_; 562 | 563 | const char* soname_; 564 | std::string realpath_; 565 | 566 | const ElfW(Versym)* versym_; 567 | 568 | ElfW(Addr) verdef_ptr_; 569 | size_t verdef_cnt_; 570 | 571 | ElfW(Addr) verneed_ptr_; 572 | size_t verneed_cnt_; 573 | 574 | uint32_t target_sdk_version_; 575 | 576 | // version >= 3 577 | std::vector dt_runpath_; 578 | android_namespace_t* primary_namespace_; 579 | android_namespace_list_t secondary_namespaces_; 580 | uintptr_t handle_; 581 | 582 | friend soinfo* get_libdl_info(); 583 | }; 584 | ``` 585 | 586 | 关注一下可以发现,soinfo结构体里包含的只有`segment table`的信息,并不包含section的信息 587 | 588 | --- 589 | 590 | 注意发现,其获取soinfo的信息是通过一个叫`find_containing_library` 的方法,这个是检测so文件是否已经加载到内存中,如果已经加载到内存中,就可以直接return了。 591 | 592 | 如果尚未加载到内存中,则会通过`find_library` 函数获取soinfo信息 593 | 594 | ```cpp 595 | // ./bioni/linker/linker.cpp 596 | 597 | static soinfo* find_library(android_namespace_t* ns, 598 | const char* name, int rtld_flags, 599 | const android_dlextinfo* extinfo, 600 | soinfo* needed_by) { 601 | soinfo* si; 602 | if (name == nullptr) { 603 | si = somain; 604 | } else if (!find_libraries(ns, needed_by, &name, 1, &si, nullptr, 0, rtld_flags, 605 | extinfo, /* add_as_children */ false)) { 606 | return nullptr; 607 | } 608 | return si; 609 | } 610 | 611 | static bool find_libraries(android_namespace_t* ns, 612 | soinfo* start_with, 613 | const char* const library_names[], 614 | size_t library_names_count, soinfo* soinfos[], 615 | std::vector* ld_preloads, 616 | size_t ld_preloads_count, int rtld_flags, 617 | const android_dlextinfo* extinfo, 618 | bool add_as_children) { 619 | // Step 0: prepare. 620 | LoadTaskList load_tasks; 621 | std::unordered_map readers_map; 622 | 623 | for (size_t i = 0; i < library_names_count; ++i) { 624 | const char* name = library_names[i]; 625 | load_tasks.push_back(LoadTask::create(name, start_with, &readers_map)); 626 | } 627 | 628 | // Construct global_group. 629 | soinfo::soinfo_list_t global_group = make_global_group(ns); 630 | 631 | // If soinfos array is null allocate one on stack. 632 | // The array is needed in case of failure; for example 633 | // when library_names[] = {libone.so, libtwo.so} and libone.so 634 | // is loaded correctly but libtwo.so failed for some reason. 635 | // In this case libone.so should be unloaded on return. 636 | // See also implementation of failure_guard below. 637 | 638 | if (soinfos == nullptr) { 639 | size_t soinfos_size = sizeof(soinfo*)*library_names_count; 640 | soinfos = reinterpret_cast(alloca(soinfos_size)); 641 | memset(soinfos, 0, soinfos_size); 642 | } 643 | 644 | // list of libraries to link - see step 2. 645 | size_t soinfos_count = 0; 646 | 647 | auto scope_guard = make_scope_guard([&]() { 648 | for (LoadTask* t : load_tasks) { 649 | LoadTask::deleter(t); 650 | } 651 | }); 652 | 653 | auto failure_guard = make_scope_guard([&]() { 654 | // Housekeeping 655 | soinfo_unload(soinfos, soinfos_count); 656 | }); 657 | 658 | ZipArchiveCache zip_archive_cache; 659 | 660 | // Step 1: expand the list of load_tasks to include 661 | // all DT_NEEDED libraries (do not load them just yet) 662 | for (size_t i = 0; iget_needed_by(); 665 | 666 | bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children); 667 | task->set_extinfo(is_dt_needed ? nullptr : extinfo); 668 | task->set_dt_needed(is_dt_needed); 669 | 670 | if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) { 671 | return false; 672 | } 673 | 674 | soinfo* si = task->get_soinfo(); 675 | 676 | if (is_dt_needed) { 677 | needed_by->add_child(si); 678 | } 679 | 680 | if (si->is_linked()) { 681 | si->increment_ref_count(); 682 | } 683 | 684 | // When ld_preloads is not null, the first 685 | // ld_preloads_count libs are in fact ld_preloads. 686 | if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) { 687 | ld_preloads->push_back(si); 688 | } 689 | 690 | if (soinfos_count < library_names_count) { 691 | soinfos[soinfos_count++] = si; 692 | } 693 | } 694 | 695 | // Step 2: Load libraries in random order (see b/24047022) 696 | LoadTaskList load_list; 697 | for (auto&& task : load_tasks) { 698 | soinfo* si = task->get_soinfo(); 699 | auto pred = [&](const LoadTask* t) { 700 | return t->get_soinfo() == si; 701 | }; 702 | 703 | if (!si->is_linked() && 704 | std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) { 705 | load_list.push_back(task); 706 | } 707 | } 708 | shuffle(&load_list); 709 | 710 | for (auto&& task : load_list) { 711 | if (!task->load()) { 712 | return false; 713 | } 714 | } 715 | 716 | // Step 3: pre-link all DT_NEEDED libraries in breadth first order. 717 | for (auto&& task : load_tasks) { 718 | soinfo* si = task->get_soinfo(); 719 | if (!si->is_linked() && !si->prelink_image()) { 720 | return false; 721 | } 722 | } 723 | 724 | // Step 4: Add LD_PRELOADed libraries to the global group for 725 | // future runs. There is no need to explicitly add them to 726 | // the global group for this run because they are going to 727 | // appear in the local group in the correct order. 728 | if (ld_preloads != nullptr) { 729 | for (auto&& si : *ld_preloads) { 730 | si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL); 731 | } 732 | } 733 | 734 | 735 | // Step 5: link libraries. 736 | soinfo::soinfo_list_t local_group; 737 | walk_dependencies_tree( 738 | (start_with != nullptr && add_as_children) ? &start_with : soinfos, 739 | (start_with != nullptr && add_as_children) ? 1 : soinfos_count, 740 | [&] (soinfo* si) { 741 | local_group.push_back(si); 742 | return true; 743 | }); 744 | 745 | // We need to increment ref_count in case 746 | // the root of the local group was not linked. 747 | bool was_local_group_root_linked = local_group.front()->is_linked(); 748 | 749 | bool linked = local_group.visit([&](soinfo* si) { 750 | if (!si->is_linked()) { 751 | if (!si->link_image(global_group, local_group, extinfo)) { 752 | return false; 753 | } 754 | } 755 | 756 | return true; 757 | }); 758 | 759 | if (linked) { 760 | local_group.for_each([](soinfo* si) { 761 | if (!si->is_linked()) { 762 | si->set_linked(); 763 | } 764 | }); 765 | 766 | failure_guard.disable(); 767 | } 768 | 769 | if (!was_local_group_root_linked) { 770 | local_group.front()->increment_ref_count(); 771 | } 772 | 773 | return linked; 774 | } 775 | 776 | ``` 777 | 778 | 注意到,27行有一个`ELFReader` ,找到他的定义处 779 | 780 | ```cpp 781 | // ./bionic/linker/linker_phdr.h 782 | 783 | class ElfReader { 784 | public: 785 | ElfReader(); 786 | 787 | bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size); 788 | bool Load(const android_dlextinfo* extinfo); 789 | 790 | const char* name() const { return name_.c_str(); } 791 | size_t phdr_count() const { return phdr_num_; } 792 | ElfW(Addr) load_start() const { return reinterpret_cast(load_start_); } 793 | size_t load_size() const { return load_size_; } 794 | ElfW(Addr) load_bias() const { return load_bias_; } 795 | const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; } 796 | const ElfW(Dyn)* dynamic() const { return dynamic_; } 797 | const char* get_string(ElfW(Word) index) const; 798 | bool is_mapped_by_caller() const { return mapped_by_caller_; } 799 | 800 | private: 801 | bool ReadElfHeader(); 802 | bool VerifyElfHeader(); 803 | bool ReadProgramHeaders(); 804 | bool ReadSectionHeaders(); 805 | bool ReadDynamicSection(); 806 | bool ReserveAddressSpace(const android_dlextinfo* extinfo); 807 | bool LoadSegments(); 808 | bool FindPhdr(); 809 | bool CheckPhdr(ElfW(Addr)); 810 | bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment); 811 | 812 | bool did_read_; 813 | bool did_load_; 814 | std::string name_; 815 | int fd_; 816 | off64_t file_offset_; 817 | off64_t file_size_; 818 | 819 | ElfW(Ehdr) header_; 820 | size_t phdr_num_; 821 | 822 | MappedFileFragment phdr_fragment_; 823 | const ElfW(Phdr)* phdr_table_; 824 | 825 | MappedFileFragment shdr_fragment_; 826 | const ElfW(Shdr)* shdr_table_; 827 | size_t shdr_num_; 828 | 829 | MappedFileFragment dynamic_fragment_; 830 | const ElfW(Dyn)* dynamic_; 831 | 832 | MappedFileFragment strtab_fragment_; 833 | const char* strtab_; 834 | size_t strtab_size_; 835 | 836 | // First page of reserved address space. 837 | void* load_start_; 838 | // Size in bytes of reserved address space. 839 | size_t load_size_; 840 | // Load bias. 841 | ElfW(Addr) load_bias_; 842 | 843 | // Loaded phdr. 844 | const ElfW(Phdr)* loaded_phdr_; 845 | 846 | // Is map owned by the caller 847 | bool mapped_by_caller_; 848 | }; 849 | ``` 850 | 851 | 从其private的方法就能看出,有一系列读取ELF信息的操作。 852 | 853 | 这里要说明一下,这里显然有`ReadSectionHeaders()` 和 `ReadDynamicSection()` 两个函数,这在4.x的安卓源码中是没有的,别的没看过,并不清楚。 854 | 855 | 在ELFReader中也对应多了一个`Read`的函数,这是用来读取一个ELF的信息,但是真正运行的时候只需要其加载到内存中,也即是`Load` 函数。而`Load`函数中则只需要segment的信息 856 | 857 | ```cpp 858 | bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file_size) { 859 | CHECK(!did_read_); 860 | CHECK(!did_load_); 861 | name_ = name; 862 | fd_ = fd; 863 | file_offset_ = file_offset; 864 | file_size_ = file_size; 865 | 866 | if (ReadElfHeader() && 867 | VerifyElfHeader() && 868 | ReadProgramHeaders() && 869 | ReadSectionHeaders() && 870 | ReadDynamicSection()) { 871 | did_read_ = true; 872 | } 873 | 874 | return did_read_; 875 | } 876 | 877 | bool ElfReader::Load(const android_dlextinfo* extinfo) { 878 | CHECK(did_read_); 879 | CHECK(!did_load_); 880 | if (ReserveAddressSpace(extinfo) && 881 | LoadSegments() && 882 | FindPhdr()) { 883 | did_load_ = true; 884 | } 885 | 886 | return did_load_; 887 | } 888 | ``` 889 | 890 | 891 | 892 | 总的来说,在Android运行时,对于一个so,只需要用到它的segment信息,由此可以对section部分进行删除,而ida等工具静态分析都是通过section的信息进行分析的,所以由此可以有效地防止so被静态分析逆向。 893 | 894 | --- 895 | 896 | 注意到下面还有调用`si->call_constructors()` 897 | 898 | ```cpp 899 | void soinfo::call_constructors() { 900 | if (constructors_called) { 901 | return; 902 | } 903 | 904 | // We set constructors_called before actually calling the constructors, otherwise it doesn't 905 | // protect against recursive constructor calls. One simple example of constructor recursion 906 | // is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so: 907 | // 1. The program depends on libc, so libc's constructor is called here. 908 | // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so. 909 | // 3. dlopen() calls the constructors on the newly created 910 | // soinfo for libc_malloc_debug_leak.so. 911 | // 4. The debug .so depends on libc, so CallConstructors is 912 | // called again with the libc soinfo. If it doesn't trigger the early- 913 | // out above, the libc constructor will be called again (recursively!). 914 | constructors_called = true; 915 | 916 | if (!is_main_executable() && preinit_array_ != nullptr) { 917 | // The GNU dynamic linker silently ignores these, but we warn the developer. 918 | PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath()); 919 | } 920 | 921 | get_children().for_each([] (soinfo* si) { 922 | si->call_constructors(); 923 | }); 924 | 925 | TRACE("\"%s\": calling constructors", get_realpath()); 926 | 927 | // DT_INIT should be called before DT_INIT_ARRAY if both are present. 928 | call_function("DT_INIT", init_func_); 929 | call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false); 930 | } 931 | ``` 932 | 933 | 这个函数通过执行`.init(_array)`定义的内容,从而完成so的初始化 934 | 935 | --- 936 | 937 | `dlopen`的内容就不继续探究了,这里主要是有关Linux动态链接库方面的内容了。 938 | 939 | 总结一下 940 | 941 | Android对so的加载 942 | 943 | 1. 通过`System.loadLibrary` 传递so的路径、classLoader等信息,然后进入native代码 944 | 2. 进入native代码后,通过调用`android::OpenNativeLibrary` 函数,跳转到dlopen,加载so到内存 945 | 3. 在dlopen中,会通过执行`.init(array)` 的内容进行so的一些动态链接信息初始化 946 | 4. `android::OpenNativeLibrary` 执行完后,会调用so中`JNI_Onload`函数,从而完成native函数的注册 947 | 948 | 949 | --- 950 | 951 | ###### Android 7.1.1的代码相比4.x的源码复杂了好多…… 952 | 953 | -------------------------------------------------------------------------------- /thinking/elf修复思路.md: -------------------------------------------------------------------------------- 1 | author: giglf 2 | 3 | [TOC] 4 | 5 | --- 6 | 7 | # 基础知识 8 | 9 | ***以下思路公式均基于32位的.so文件*** 10 | 11 | 1. 根据Android Linker的代码可知,so的加载过程并不需要用到section信息,但需要segment的信息,segment的信息完整的保留了下来 12 | 13 | 2. 针对的是so文件(Shared library),必定包含`.dynamic section` 14 | 15 | 3. 对于offset和addr的确定,通过segment的offset和vaddr确定,合并于同一个segment的section,则紧接上一个section对齐后的地址 16 | 17 | 4. `.hash`的结构决定了只要定位起始位置便可确定其大小 18 | 19 | ![hash](./symbol_hash_table.png) 20 | 21 | 5. ELF将`GOT`表拆分成了两个表`.got` `.got.plt` , 其中`.got`用来保存全局变量引用的地址,`.got.plt`用来保存函数引用的地址。 22 | 23 | 并且,`.got.plt` 的第一项为`.dynamic` 段的地址,第二项为本模块的ID,第三项为`_dl_runtime_resolve()` 的地址。 24 | 25 | `.got.plt`在ELF文件中的段名为`.plt` 26 | 27 | 而`.plt`段中,每一项占12字节,每一项都是一小片段代码 28 | 29 | ![plt](./plt.jpg) 30 | 31 | 6. 在`.got`中,以`_global_offset_table_`作分界,在其之前为`.rel.dyn` ,在其之后半部分为`.rel.plt` ,因此可知道这种方式计算出`.got`的尾部 32 | 33 | ![global_offset_table](global_offset_table.png) 34 | 35 | ![global_offset_table2](global_offset_table2.png) 36 | 37 | 7. `.bss` section属性为NOBITS,长度信息无关紧要 38 | 39 | 40 | 41 | # SO结构信息读取 42 | 43 | #### ELF Header (Elf_Ehdr) ELF文件头 44 | 45 | 1. 读取第5个字节,判断ELF为32位还是64位,define相应的宏 46 | 2. 直接按结构体大小读取header头部 47 | 48 | #### Sections Header (Elf_Shdr) 节区头部 49 | 50 | * ELF_Chdr(Section compression header)When SHF_COMPRESSED is set. 51 | 52 | 53 | 1. 通过Elf_Ehdr.e_shoff确定Section Table的偏移 54 | 2. 通过Elf_Ehdr.e_shnum确定Section的个数 55 | 3. 通过Elf_Ehdr.e_shentsize确定Section数据结构的大小 56 | 4. 通过Elf_Ehdr.e_shstrndx确定字符串Section的索引 57 | 58 | 59 | #### Symbol Table (Elf_Sym) 符号表 60 | 61 | * ELF_Syminfo 62 | * The syminfo section if available contains additional information about 63 | every dynamic symbol. 64 | * *暂不知作用 65 | 66 | ####Program Header (Elf_Phdr) 程序头部 67 | 68 | 1. 通过Elf_Ehdr.e_phoff确定Program Header Table的偏移 69 | 2. 通过Elf_Ehdr.e_phnum确定Program (segment)的个数 70 | 3. 通过Elf_Ehdr.e_phentsize确定Program Header 数据结构的大小 71 | 72 | 73 | --- 74 | 75 | # 修复思路 76 | 77 | * segment table完整 78 | 79 | **p_type == PT_INERP** : 直接映射到`.interp` 节 **addr = offset** 80 | 81 | **p_type == PT_DYNAMIC** : 直接映射到`.dynamic` 节 82 | 83 | **p_type == PT_ARM_EXIDX** : 直接映射到 `.ARM.exidx` 节 **addr = offset** 84 | 85 | ### 直接定位 86 | 87 | 定位到`.dynamic` 节,通过 entry tag确定section信息 88 | 89 | * ​ 90 | 91 | * `DT_STRTAB`, `DT_STRSZ` => `.dynstr` 92 | * `DT_SYMTAB`, `DT_SYMENT` => `.dynsym` 93 | * `DT_RELA` , `DT_RELASZ`, `DR_RELAENT` => `.rela` 94 | 95 | * `DT_INIT` => `.init` 96 | 97 | * `DT_FINI` => `.fini` 98 | 99 | * `DT_REL`, `DT_RELSZ`, `DT_RELENT` => `.rel.dyn` 100 | * `DT_JMPREL`, `DT_PLTRELSZ` => `.rel.plt` 101 | * `DT_INIT_ARRAY`, `DT_INIT_ARRAYSZ` => `.init_array` -> s_addr 102 | * `DT_FINI_ARRAY`, `DT_FINI_ARRAYSZ` => `.fini_array` -> s_addr 103 | 104 | 105 | ### 间接确定 106 | 107 | - `DT_HASH` => `.hash` 108 | 109 | 读前面两项 110 | $$ 111 | size = (nbucket + nchain + 2) * sizeof(int) 112 | $$ 113 | 114 | - `.plt` => 起始位置即为`.rel.plt`的末尾,上面处理可知`.plt`的offset和vaddr,plt 由固定16 字节 + 4 字节的`__global__offset_table` 变量和n 个需要重定位的函数地址构成,函数地址又与rel.plt 115 | 中的结构一一对应。故 116 | $$ 117 | size = 20 + 12 * (rel.plt.size) / sizeof(Elf32\_Rel) 118 | $$ 119 | 120 | - `.got` => `.got` 紧接着`.dynamic` ,并且,通过`DT_PLTGOT` 获得`_global_offset_table_`的地址,通过`.rel.plt` 的size算出`.got` 的尾地址,以此计算出`.got` 的size 121 | $$ 122 | size = addr(\_global\_offset\_table\_) +4*(.rel.plt.size)/sizeof(ELF32\_Rel) + 4*3 - addr(.got) 123 | $$ 124 | 125 | - `.data` => `.got` 的尾部即为.data段的地址,因为`.bss`不占空间,故`.data` 段的尾部即为load2的尾部 126 | 127 | - `.bss` => `.bss`紧接`.data` ,但为NOBITS属性,其size无关紧要 128 | 129 | - `.shstrtab` => 储存各header name,放在section header的尾部,并把`string table index` patch回到elf_header 130 | 131 | - `.text &.ARM.extab ` => offset和vaddr通过plt的末尾得到,长度通过`.ARM.extab` 的起始位置和plt的末尾位置计算所得,但未能想到区分方法,暂时合并,修复后的`.ARM.extab` 在ida会解析错误 132 | 133 | 134 | 135 | 136 | # 修复分类 137 | 138 | 分类,鉴定section的损毁程度,按照缺失信息逐个修复 139 | 140 | 在此,把读到的so文件分为几种不同的情况,进行修复 141 | 142 | 1. segment损毁、非elf文件,完全损毁,无法加载,放弃修复 143 | 2. 单纯从elf_header抹去section偏移等信息,直接通过读取section,修复 144 | * 通过number和section header entry size计算出section header的大小,从尾部偏移到,修复elf头 145 | 3. 只抹掉section的addr和offset,size及其他信息都有保留。此时elf_header中仍然包含section header的偏移,是完整的,定位到section header table 146 | * 通过elf_header定位到section header 147 | * 逐个section header读取size,对应segment,进行修复 148 | * 这种修复能最大可能修复到so的原本状态 149 | 4. section面目全非,直接通过上面思路进行section header的重建 150 | 151 | 上述情况中,2的情况可能性不大,为此着重考虑3、4两种修复方式 152 | 153 | 154 | 155 | # 修复方案 156 | 157 | 针对上述情况,修复方案分成Plan A 和Plan B 158 | 159 | ### Plan A 160 | 161 | 在经过校验`ELf Header ` 和`Program header` 完整,而`Section Header` 仅仅丢失addresse和offset的情况下选择 162 | 163 | 抽出shdr_table部分,根据`Program header` LOAD的部分和每个section的size修复相应的address和offset 164 | 165 | 最后结合输出到文件 166 | 167 | ### Plan B 168 | 169 | B方案比较复杂,首先讨论一个问题,什么情况下会出现section缺失的情况 170 | 171 | 1. so文件经过人为的混淆,防止被逆向静态分析 172 | 2. 该so文件是在调试的时候从内存dump出来的。elf的执行视图不包含section字段 173 | 174 | 因为so文件是从内存中dump出来的,自然包含有偏移 175 | 176 | 总结出一种统一的修复方式,先模拟加载so到内存,然后记录下相应的soinfo,就像Android源码中的LOAD操作一样(详情参考《AndroidSO加载过程》),然后从soinfo中获取so的信息,rebuild section header,最后整合到rebuild的文件中。 177 | 178 | 179 | 180 | 读取,加载的大部分代码可以直接从Android源码中修改过来 -------------------------------------------------------------------------------- /thinking/global_offset_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/thinking/global_offset_table.png -------------------------------------------------------------------------------- /thinking/global_offset_table2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/thinking/global_offset_table2.png -------------------------------------------------------------------------------- /thinking/plt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/thinking/plt.jpg -------------------------------------------------------------------------------- /thinking/symbol_hash_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giglf/SoRebuilder/548cdf946fa40564610d30e9452c4ef547636838/thinking/symbol_hash_table.png --------------------------------------------------------------------------------