├── .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 | 
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 | 
30 |
31 | 6. 在`.got`中,以`_global_offset_table_`作分界,在其之前为`.rel.dyn` ,在其之后半部分为`.rel.plt` ,因此可知道这种方式计算出`.got`的尾部
32 |
33 | 
34 |
35 | 
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
--------------------------------------------------------------------------------