{"id":217,"date":"2020-12-31T13:03:41","date_gmt":"2020-12-31T05:03:41","guid":{"rendered":"http:\/\/pareto.fun\/?p=217"},"modified":"2022-08-12T20:09:40","modified_gmt":"2022-08-12T12:09:40","slug":"android-linker%e8%a7%a3%e8%af%bb-2","status":"publish","type":"post","link":"http:\/\/pareto.fun\/?p=217","title":{"rendered":"android linker\u89e3\u8bfb\u2014\u20142"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">step 0\u9636\u6bb5\uff0c\u521b\u5efa\u4e00\u4e2a\u5217\u8868<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\"> &nbsp;\/\/ Step 0: prepare.<br> &nbsp;LoadTaskList load_tasks;<br>\u200b<br> &nbsp;for (size_t i = 0; i &lt; library_names_count; ++i) {<br> &nbsp; &nbsp;const char* name = library_names[i];<br> &nbsp; &nbsp;LD_LOG(kLogDlopen,\"[linker.cpp] step 1 ,so_name\",name);<br>\u200b<br> &nbsp; &nbsp;load_tasks.push_back(LoadTask::create(name, start_with, ns, &amp;readers_map));<br>  }<br>\u200b<br> &nbsp;\/\/ If soinfos array is null allocate one on stack.<br> &nbsp;\/\/ The array is needed in case of failure; for example<br> &nbsp;\/\/ when library_names[] = {libone.so, libtwo.so} and libone.so<br> &nbsp;\/\/ is loaded correctly but libtwo.so failed for some reason.<br> &nbsp;\/\/ In this case libone.so should be unloaded on return.<br> &nbsp;\/\/ See also implementation of failure_guard below.<br>\u200b<br> &nbsp;if (soinfos == nullptr) {<br> &nbsp; &nbsp;size_t soinfos_size = sizeof(soinfo*)*library_names_count;<br> &nbsp; &nbsp;soinfos = reinterpret_cast&lt;soinfo**&gt;(alloca(soinfos_size));<br> &nbsp; &nbsp;memset(soinfos, 0, soinfos_size);<br>  }<br>\u200b<br> &nbsp;\/\/ list of libraries to link - see step 2.<br> &nbsp;size_t soinfos_count = 0;<br>\u200b<br> &nbsp;auto scope_guard = android::base::make_scope_guard([&amp;]() {<br> &nbsp; &nbsp;for (LoadTask* t : load_tasks) {<br> &nbsp; &nbsp; &nbsp;LD_LOG(kLogDlopen,\"[linker.cpp] before call deleter %s\",t-&gt;get_name());<br> &nbsp; &nbsp; &nbsp;LoadTask::deleter(t);<br> &nbsp;  }<br>  });<br>\u200b<br> &nbsp;auto failure_guard = android::base::make_scope_guard([&amp;]() {<br> &nbsp; &nbsp;\/\/ Housekeeping<br> &nbsp; &nbsp;soinfo_unload(soinfos, soinfos_count);<br>  });<br>\u200b<br> &nbsp;ZipArchiveCache zip_archive_cache;<br>\u200b<\/pre>\n\n\n\n<p>\u6211\u4eec\u8ddf\u8e2a\u521b\u5efaLoadtask\u8fc7\u7a0b\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"953\" height=\"267\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118111340146.png\" alt=\"\" class=\"wp-image-171\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118111340146.png 953w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118111340146-300x84.png 300w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118111340146-768x215.png 768w\" sizes=\"(max-width: 953px) 100vw, 953px\" \/><\/figure>\n\n\n\n<p>\u8be5\u51fd\u6570\u8c03\u7528LoadTask\u7684\u91cd\u8f7d\u51fd\u6570\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  static LoadTask* create(const char* name,\n                          soinfo* needed_by,\n                          android_namespace_t* start_from,\n                          std::unordered_map&lt;const soinfo*, ElfReader&gt;* readers_map) {\n    LoadTask* ptr = TypeBasedAllocator&lt;LoadTask&gt;::alloc();\n    return new (ptr) LoadTask(name, needed_by, start_from, readers_map);\n  }<\/pre>\n\n\n\n<p>\u8be5\u51fd\u6570\u5b8c\u6210\u5404\u4e2a\u6210\u5458\u7684\u8d4b\u503c\uff0c\u7b80\u5355\u770b\u4e0b\u54ea\u4e9b\u6210\u5458\u88ab\u8d4b\u503c\uff0c\u540d\u79f0\uff0cneeded_by \uff0celf_reader_map_ , start_from.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  LoadTask(const char* name,\n           soinfo* needed_by,\n           android_namespace_t* start_from,\n           std::unordered_map&lt;const soinfo*, ElfReader&gt;* readers_map)\n    : name_(name), needed_by_(needed_by), si_(nullptr),\n      fd_(-1), close_fd_(false), file_offset_(0), elf_readers_map_(readers_map),\n      is_dt_needed_(false), start_from_(start_from) {}<\/code><\/pre>\n\n\n\n<p>\u8ffd\u6eafneeded_by \u6765\u5386\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"710\" height=\"117\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117211631582.png\" alt=\"\" class=\"wp-image-168\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117211631582.png 710w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117211631582-300x49.png 300w\" sizes=\"(max-width: 710px) 100vw, 710px\" \/><\/figure>\n\n\n\n<p>\u67e5\u770b__builtin_return_address() \u7684\u8bf4\u660e , \u8fd4\u56de\u8c03\u7528\u51fd\u6570\u7684\u5730\u5740\uff0cg++\u7684\u5185\u5efa\u51fd\u6570 \uff0c\u53ef\u4ee5\u83b7\u53d6\u5230\u8c03\u7528\u51fd\u6570\u65f6\u7684ret\u5730\u5740\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"619\" height=\"198\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117212757895.png\" alt=\"\" class=\"wp-image-169\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117212757895.png 619w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201117212757895-300x96.png 300w\" sizes=\"(max-width: 619px) 100vw, 619px\" \/><\/figure>\n\n\n\n<p>\u5728\u8be5\u51fd\u6570\u5c06\u5176\u8f6c\u6362\u4e3asoinfo \u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"230\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118095629433-1024x230.png\" alt=\"\" class=\"wp-image-170\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118095629433-1024x230.png 1024w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118095629433-300x67.png 300w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118095629433-768x172.png 768w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/11\/image-20201118095629433.png 1056w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>find_containing_library \u8fd4\u56de\u8c03\u7528\u51fd\u6570\u6240\u5728\u6a21\u5757\u7684soinfo<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">soinfo* find_containing_library(const void* p) {\n  ElfW(Addr) address = reinterpret_cast&lt;ElfW(Addr)&gt;(p);\n  for (soinfo* si = solist_get_head(); si != nullptr; si = si-&gt;next) {\n    if (address &gt;= si-&gt;base &amp;&amp; address - si-&gt;base &lt; si-&gt;size) {\n      return si;\n    }\n  }\n  return nullptr;\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1 \u62d3\u5c55\u5217\u8868\u6765\u5305\u542b\u6240\u6709DT_NEEDED \u5e93<\/h3>\n\n\n\n<p>\u8be5\u6b65\u9aa4\u7ed9\u5217\u8868\u4e2d\u589e\u52a0so\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> \/\/ Step 1: expand the list of load_tasks to include<br> &nbsp;\/\/ all DT_NEEDED libraries (do not load them just yet)<br> &nbsp;for (size_t i = 0; i&lt;load_tasks.size(); ++i) {<br> &nbsp; &nbsp;LoadTask* task = load_tasks[i];<br> &nbsp; &nbsp;soinfo* needed_by = task-&gt;get_needed_by();<br> &nbsp; &nbsp;bool is_dt_needed = needed_by != nullptr &amp;&amp; (needed_by != start_with || add_as_children);<br> &nbsp; &nbsp;task-&gt;set_extinfo(is_dt_needed ? nullptr : extinfo);<br> &nbsp; &nbsp;task-&gt;set_dt_needed(is_dt_needed);<br>\u200b<br>\/*<br>try to find the load.Note: start from the namespace that is stored in the LoadTask. This namespace is different from the current namespace when the LoadTask is for a transitive dependency and the lib that created the LoadTask is not found in the current namespace but in one of the linked namespace.<br>*\/<br> &nbsp; &nbsp;if (!find_library_internal(const_cast&lt;android_namespace_t*&gt;(task-&gt;get_start_from()),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; task,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;zip_archive_cache,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;load_tasks,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rtld_flags,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search_linked_namespaces || is_dt_needed)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;soinfo* si = task-&gt;get_soinfo();<br>\u200b<br> &nbsp; &nbsp;if (is_dt_needed) {<br> &nbsp; &nbsp; &nbsp;needed_by-&gt;add_child(si);<br>\u200b<br> &nbsp; &nbsp; &nbsp;if (si-&gt;is_linked()) {<br> &nbsp; &nbsp; &nbsp; &nbsp;si-&gt;increment_ref_count();<br> &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;\/\/ When ld_preloads is not null, the first<br> &nbsp; &nbsp;\/\/ ld_preloads_count libs are in fact ld_preloads.<br> &nbsp; &nbsp;if (ld_preloads != nullptr &amp;&amp; soinfos_count &lt; ld_preloads_count) {<br> &nbsp; &nbsp; &nbsp;ld_preloads-&gt;push_back(si);<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;if (soinfos_count &lt; library_names_count) {<br> &nbsp; &nbsp; &nbsp;soinfos[soinfos_count++] = si;<br> &nbsp;  }<br>  }<br>\u200b<\/pre>\n\n\n\n<p>\u7b5b\u9009\u8981\u8f7d\u5165\u7684load_list \u5e76\u89e3\u6790elf\u6587\u4ef6\u7684so<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> &nbsp;\/\/ Step 2: Load libraries in random order (see b\/24047022)<br> &nbsp;LoadTaskList load_list;<br> &nbsp;for (auto&amp;&amp; task : load_tasks) {<br> &nbsp; &nbsp;soinfo* si = task-&gt;get_soinfo();<br> &nbsp; &nbsp;auto pred = [&amp;](const LoadTask* t) {<br> &nbsp; &nbsp; &nbsp;return t-&gt;get_soinfo() == si;<br> &nbsp;  };<br>\u200b<br> &nbsp; &nbsp;if (!si-&gt;is_linked() &amp;&amp;<br> &nbsp; &nbsp; &nbsp; &nbsp;std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) {<br> &nbsp; &nbsp; &nbsp;load_list.push_back(task);<br> &nbsp;  }<br>  }<br> &nbsp;shuffle(&amp;load_list);<br>\u200b<br> &nbsp;for (auto&amp;&amp; task : load_list) {<br> &nbsp; &nbsp; &nbsp;\/\/*** \u770b\u770b\u8fd9\u4e2aloda\u51fd\u6570<br> &nbsp; &nbsp;if (!task-&gt;load()) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<\/pre>\n\n\n\n<p>\u8fd9\u4e2aelf_reader \u5c31\u662f\u5bf9\u5e94so\u7528\u6765\u89e3\u6790elf\u6587\u4ef6\u7684\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> &nbsp;bool load() {<br> &nbsp; &nbsp;ElfReader&amp; elf_reader = get_elf_reader();<br> &nbsp; &nbsp; &nbsp;\/\/\u5728elf_read.Load \u4e0b\u5b8c\u6210elf\u6587\u4ef6\u7a7a\u95f4\u7684\u5206\u914d\u548c\u89e3\u6790 \uff0c\u8fd8\u4e0d\u80fd\u7b97\u8f7d\u5165\u4e86so\u3002<br> &nbsp; &nbsp;if (!elf_reader.Load(extinfo_)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br> &nbsp; &nbsp;si_-&gt;base = elf_reader.load_start();<br> &nbsp; &nbsp;si_-&gt;size = elf_reader.load_size();<br> &nbsp; &nbsp;si_-&gt;set_mapped_by_caller(elf_reader.is_mapped_by_caller());<br> &nbsp; &nbsp;si_-&gt;load_bias = elf_reader.load_bias();<br> &nbsp; &nbsp;LD_LOG(kLogDlopen,\"[linker.cpp] Step2 load_bias %p \",si_-&gt;load_bias);<br> &nbsp; &nbsp;si_-&gt;phnum = elf_reader.phdr_count();<br> &nbsp; &nbsp;si_-&gt;phdr = elf_reader.loaded_phdr();<br> &nbsp; &nbsp;return true;<br>  }<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step3 <\/h3>\n\n\n\n<p>Step3\u8fc7\u7a0b\u89e3\u6790ELF\u6587\u4ef6\u83b7\u53d6\u76f8\u5e94\u5b57\u6bb5\u7684\u503c<\/p>\n\n\n\n<p>\u9884\u8fde\u63a5\u6240\u6709DT_NEEDED \u5e93, \u903b\u8f91\u7b80\u5355\uff0c\u6ca1\u6709\u88ab\u8fde\u63a5\u8fc7\uff0c\u5219\u8c03\u7528prelink_image()\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  \/\/ Step 3: pre-link all DT_NEEDED libraries in breadth first order.<br>  for (auto&amp;&amp; task : load_tasks) {<br> &nbsp;  soinfo* si = task-&gt;get_soinfo();<br> &nbsp;  if (!si-&gt;is_linked() &amp;&amp; !si-&gt;prelink_image()) {<br> &nbsp; &nbsp;  return false;<br> &nbsp;  }<br>  }<\/pre>\n\n\n\n<p>prelink_image\uff0c\u8bfb\u53d6\u5404\u7c7b\u578b\u7684\u6bb5 \uff0c \u4f9d\u6b21\u770b\u5168\u592a\u809d\u4e86 \uff0c \u540e\u671f\u5728\u8fd9\u91cc\u67e5\u5b57\u6bb5\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step4<\/h3>\n\n\n\n<p>\u7565<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">linkerStep5-linkerStep6<\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\"> \/\/ Step 5: link libraries that are not destined to this namespace.<br> &nbsp;\/\/ Do this by recursively calling find_libraries on the namespace where the lib<br> &nbsp;\/\/ was found during Step 1.<br> &nbsp;for (auto&amp;&amp; task : load_tasks) {<br> &nbsp; &nbsp;soinfo* si = task-&gt;get_soinfo();<br> &nbsp; &nbsp;if (si-&gt;get_primary_namespace() != ns) {<br> &nbsp; &nbsp; &nbsp;const char* name = task-&gt;get_name();<br> &nbsp; &nbsp; &nbsp;if (find_libraries(si-&gt;get_primary_namespace(), task-&gt;get_needed_by(), &amp;name, 1,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nullptr \/* soinfos *\/, nullptr \/* ld_preloads *\/, 0 \/* ld_preload_count *\/,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rtld_flags, nullptr \/* extinfo *\/, false \/* add_as_children *\/,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false \/* search_linked_namespaces *\/, readers_map, namespaces)) {<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ If this lib is directly needed by one of the libs in this namespace,<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ then increment the count<br> &nbsp; &nbsp; &nbsp; &nbsp;soinfo* needed_by = task-&gt;get_needed_by();<br> &nbsp; &nbsp; &nbsp; &nbsp;if (needed_by != nullptr &amp;&amp; needed_by-&gt;get_primary_namespace() == ns &amp;&amp; si-&gt;is_linked()) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;si-&gt;increment_ref_count();<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp;  } else {<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp;  }<br> &nbsp;  }<br>  }<br>    \/\/\u8fde\u63a5\u8fd9\u4e2a\u547d\u540d\u7a7a\u95f4\u7684\u5e93\u6587\u4ef6<br> &nbsp;\/\/ Step 6: link libraries in this namespace<br> &nbsp;soinfo_list_t local_group;<br> &nbsp;walk_dependencies_tree(<br> &nbsp; &nbsp;  (start_with != nullptr &amp;&amp; add_as_children) ? &amp;start_with : soinfos,<br> &nbsp; &nbsp;  (start_with != nullptr &amp;&amp; add_as_children) ? 1 : soinfos_count,<br> &nbsp; &nbsp;  [&amp;] (soinfo* si) {<br> &nbsp; &nbsp;if (ns-&gt;is_accessible(si)) {<br> &nbsp; &nbsp; &nbsp;local_group.push_back(si);<br> &nbsp; &nbsp; &nbsp;return kWalkContinue;<br> &nbsp;  } else {<br> &nbsp; &nbsp; &nbsp;return kWalkSkip;<br> &nbsp;  }<br>  });<br> &nbsp;soinfo_list_t global_group = ns-&gt;get_global_group();<br> &nbsp;bool linked = local_group.visit([&amp;](soinfo* si) {<br> &nbsp; &nbsp;if (!si-&gt;is_linked()) {<br> &nbsp; &nbsp; &nbsp;LD_LOG(kLogDlopen,\"so %s is not linked , now try to link \",si-&gt;get_soname());<br> &nbsp; &nbsp; &nbsp;if (!si-&gt;link_image(global_group, local_group, extinfo) ||<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;!get_cfi_shadow()-&gt;AfterLoad(si, solist_get_head())) {<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp;  }<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;return true;<br>  });<br> &nbsp;if (linked) {<br> &nbsp; &nbsp;local_group.for_each([](soinfo* si) {<br> &nbsp; &nbsp; &nbsp;LD_LOG(kLogDlopen,\"travser local_group list %s\" , si-&gt;get_soname());<br> &nbsp; &nbsp; &nbsp;if (!si-&gt;is_linked()) {<br> &nbsp; &nbsp; &nbsp; &nbsp;si-&gt;set_linked();<br> &nbsp; &nbsp;  }<br> &nbsp;  });<br>\u200b<br> &nbsp; &nbsp;failure_guard.Disable();<br>  }<br>\u200b<br> &nbsp;return linked;<\/pre>\n\n\n\n<p>\u6d89\u53ca\u5230\u91cd\u5b9a\u4f4d\u7684\u955c\u50cf\u8fde\u63a5\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bool soinfo::link_image(const soinfo_list_t&amp; global_group, const soinfo_list_t&amp; local_group,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const android_dlextinfo* extinfo) {<br>\u200b<br>\u200b<br>\/\/ \u8fd9\u91cc\u4ec5\u4fdd\u7559\u4e86\u5927\u5bb6\u6bd4\u8f83\u719f\u6089\u7684\u7c7b\u578b\u3002\u5e38\u89c4\u90fd\u662frel\u3002<br>\u200b<br>#if defined(USE_RELA)<br> &nbsp;if (rela_ != nullptr) {<br> &nbsp; &nbsp;DEBUG(\"[ relocating %s ]\", get_realpath());<br> &nbsp; &nbsp;if (!relocate(version_tracker,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<br> &nbsp;if (plt_rela_ != nullptr) {<br> &nbsp; &nbsp;DEBUG(\"[ relocating %s plt ]\", get_realpath());<br> &nbsp; &nbsp;if (!relocate(version_tracker,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<br>#else<br> &nbsp; &nbsp;\/\/\u628a\u91cd\u5fc3\u653e\u5728\u8fd9\u91cc <br> &nbsp; &nbsp;<br> &nbsp;if ( != nullptr) {<br> &nbsp; &nbsp;DEBUG(\"[ relocating %s ]\", get_realpath());<br> &nbsp; &nbsp;if (!relocate(version_tracker,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<br> &nbsp;if (plt_rel_ != nullptr) {<br> &nbsp; &nbsp;LD_LOG(kLogDlopen,\"[ relocating %s plt ]\", get_realpath());<br> &nbsp; &nbsp;if (!relocate(version_tracker,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<br>#endif<br>\u200b<br>\u200b<\/pre>\n\n\n\n<p>\u5728Step3\u4e2d\u627e\u8fd9rel_ \u548cplt_rel_ \u7684\u8d4b\u503c\uff0c\u5206\u522b\u4e3aDT_JMPREL \u548c DT_REL \u5bf9\u5e94.rel.plt \u548c.rel.dyn\u6bb5 \u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     &nbsp;\/\/\u8be5\u8bb0\u5f55\u4fdd\u7559\u4ec5\u4e0e\u91cd\u5b9a\u4f4d\u76f8\u5173\u7684PLT\u8868\u7684\u5730\u5740<br>    \/* ...  *\/<br> &nbsp; &nbsp; &nbsp;case DT_JMPREL:<br>#if defined(USE_RELA)<br> &nbsp; &nbsp; &nbsp; &nbsp;plt_rela_ = reinterpret_cast&lt;ElfW(Rela)*&gt;(load_bias + d-&gt;d_un.d_ptr);<br>#else<br> &nbsp; &nbsp; &nbsp; &nbsp;plt_rel_ = reinterpret_cast&lt;ElfW(Rel)*&gt;(load_bias + d-&gt;d_un.d_ptr);<br>#endif<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br>        \/\/\u91cd\u5b9a\u4f4d\u76f8\u5173plt\u8868\u7684\u5927\u5c0f<br> &nbsp; &nbsp; &nbsp;case DT_PLTRELSZ:<br>#if defined(USE_RELA)<br> &nbsp; &nbsp; &nbsp; &nbsp;plt_rela_count_ = d-&gt;d_un.d_val \/ sizeof(ElfW(Rela));<br>#else<br> &nbsp; &nbsp; &nbsp; &nbsp;plt_rel_count_ = d-&gt;d_un.d_val \/ sizeof(ElfW(Rel));<br>#endif<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br>    \/* ...  *\/<br>     &nbsp;case DT_REL:<br> &nbsp; &nbsp; &nbsp; &nbsp;rel_ = reinterpret_cast&lt;ElfW(Rel)*&gt;(load_bias + d-&gt;d_un.d_ptr);<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br>\u200b<br> &nbsp; &nbsp; &nbsp;case DT_RELSZ:<br> &nbsp; &nbsp; &nbsp; &nbsp;rel_count_ = d-&gt;d_un.d_val \/ sizeof(ElfW(Rel));<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<\/pre>\n\n\n\n<p>\u53c2\u6570\u4e2d\u6709 plain_reloc_iterator \uff0c\u4f20\u5165rel\u7684\u8fed\u4ee3\u5668 \u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">relocate(version_tracker,plain_reloc_iterator(rel_, rel_count_), global_group, local_group) <\/pre>\n\n\n\n<p>Elf32_Rel\u7684\u7ed3\u6784\u4f53\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">typedef struct<br>{<br> &nbsp;Elf32_Addr    r_offset;       \/* Address *\/<br> &nbsp;Elf32_Word    r_info;         \/* Relocation type and symbol index *\/<br>} Elf32_Rel;<\/pre>\n\n\n\n<p>\u5bf9\u4e8eDT_REL,\u8be5\u51fd\u6570\u83b7\u53d6\u5230rel.dyn \u6bb5, \u5230\u8fd9\u91cc\u91cd\u5b9a\u4f4d\u7684\u5185\u5bb9\u5c31\u5f88\u7b80\u5355\u4e86\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">template&lt;typename ElfRelIteratorT&gt;<br>bool soinfo::relocate(const VersionTracker&amp; version_tracker, ElfRelIteratorT&amp;&amp; rel_iterator,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const soinfo_list_t&amp; global_group, const soinfo_list_t&amp; local_group){<br> &nbsp;for (size_t idx = 0; rel_iterator.has_next(); ++idx) {<br> &nbsp; &nbsp;const auto rel = rel_iterator.next();<br> &nbsp; &nbsp;if (rel == nullptr) {<br> &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br> &nbsp; &nbsp;\/\/ \u83b7\u53d6rel \u7684\u7c7b\u578b \uff0c \u548c\u7b26\u53f7\u7d22\u5f15<br> &nbsp; &nbsp;ElfW(Word) type = ELFW(R_TYPE)(rel-&gt;r_info);<br> &nbsp; &nbsp;ElfW(Word) sym = ELFW(R_SYM)(rel-&gt;r_info);<br>    \/\/rel \u5185\u5b58\u5730\u5740<br> &nbsp; &nbsp;ElfW(Addr) reloc = static_cast&lt;ElfW(Addr)&gt;(rel-&gt;r_offset + load_bias);<br> &nbsp; &nbsp;ElfW(Addr) sym_addr = 0;<br> &nbsp; &nbsp;const char* sym_name = nullptr;<br> &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp;ElfW(Addr) addend = get_addend(rel, reloc);<br>\u200b<br> &nbsp; &nbsp;DEBUG(\"Processing \\\"%s\\\" relocation at index %zd\", get_realpath(), idx);<br> &nbsp; &nbsp;if (type == R_GENERIC_NONE) {<br> &nbsp; &nbsp; &nbsp;continue;<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;const ElfW(Sym)* s = nullptr;<br> &nbsp; &nbsp;soinfo* lsi = nullptr;<br>\u200b<br> &nbsp; &nbsp;if (sym != 0) {<br> &nbsp; &nbsp; &nbsp;\/\/\u4ece\u7b26\u53f7\u8868\u4e2d\u83b7\u53d6\u5230\u7b26\u53f7\u540d\u79f0<br> &nbsp; &nbsp; &nbsp;sym_name = get_string(symtab_[sym].st_name);<br> &nbsp; &nbsp; &nbsp;const version_info* vi = nullptr;<br>\u200b<br> &nbsp; &nbsp; &nbsp;if (!lookup_version_info(version_tracker, sym, sym_name, &amp;vi)) {<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp;  }<br>    \/\/ \u8fd9\u4e2a\u51fd\u6570\u53ef\u4ee5\u89e3\u91caLD_PRELOAD \u5bf9\u4e8e\u76f8\u540c\u7b26\u53f7\u540d\u79f0linker\u7684\u5904\u7406\u65b9\u5f0f\u3002<br> &nbsp; &nbsp; &nbsp;if (!soinfo_do_lookup(this, sym_name, vi, &amp;lsi, global_group, local_group, &amp;s)) {<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp;  }<br>\u200b<br> &nbsp; &nbsp; &nbsp;if (s == nullptr) {<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ We only allow an undefined symbol if this is a weak reference...<br> &nbsp; &nbsp; &nbsp; &nbsp;s = &amp;symtab_[sym];<br> &nbsp; &nbsp; &nbsp; &nbsp;if (ELF_ST_BIND(s-&gt;st_info) != STB_WEAK) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DL_ERR(\"cannot locate symbol \\\"%s\\\" referenced by \\\"%s\\\"...\", sym_name, get_realpath());<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp; &nbsp;  }<br>\u200b<br>\u200b<br>#elif defined(__arm__)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case R_ARM_ABS32:<br>\u200b<br>#endif<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/*<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * The sym_addr was initialized to be zero above, or the relocation<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * code below does not care about value of sym_addr.<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; * No need to do anything.<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *\/<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br>#if defined(__x86_64__)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case R_X86_64_PC32:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sym_addr = reloc;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br>#elif defined(__i386__)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case R_386_PC32:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sym_addr = reloc;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br>#endif<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;default:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DL_ERR(\"unknown weak reloc type %d @ %p (%zu)\", type, rel, idx);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp;  } else { \/\/ We got a definition.<br>    \/*<br>    .......<br>    *\/<br> &nbsp; &nbsp;  }<br> &nbsp; &nbsp; &nbsp;count_relocation(kRelocSymbol);<br> &nbsp;  }<br>    \/\/ \u91cd\u5b9a\u4f4d\u8fd0\u7b97\u3002<br> &nbsp; &nbsp;switch (type) {<br> &nbsp; &nbsp; &nbsp;case R_GENERIC_JUMP_SLOT:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocAbsolute);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO JMP_SLOT %16p &lt;- %16p %s\\n\",<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(reloc),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(sym_addr + addend), sym_name);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) = (sym_addr + addend);<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp;case R_GENERIC_GLOB_DAT:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocAbsolute);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO GLOB_DAT %16p &lt;- %16p %s\\n\",<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(reloc),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(sym_addr + addend), sym_name);<br> &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) = (sym_addr + addend);<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp;case R_GENERIC_RELATIVE:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocRelative);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO RELATIVE %16p &lt;- %16p\\n\",<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(reloc),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reinterpret_cast&lt;void*&gt;(load_bias + addend));<br> &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) = (load_bias + addend);<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp;case R_GENERIC_IRELATIVE:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocRelative);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO IRELATIVE %16p &lt;- %16p\\n\",<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;reinterpret_cast&lt;void*&gt;(reloc),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;reinterpret_cast&lt;void*&gt;(load_bias + addend));<br> &nbsp; &nbsp; &nbsp;  {<br>        \/* ... *\/<br> &nbsp; &nbsp; &nbsp; &nbsp;\/* ... *\/<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) = ifunc_addr;<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br>\u200b<br>\u200b<br>#elif defined(__arm__)<br> &nbsp; &nbsp; &nbsp;case R_ARM_ABS32:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocAbsolute);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO ABS %08x &lt;- %08x %s\", reloc, sym_addr, sym_name);<br> &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) += sym_addr;<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp;case R_ARM_REL32:<br> &nbsp; &nbsp; &nbsp; &nbsp;count_relocation(kRelocRelative);<br> &nbsp; &nbsp; &nbsp; &nbsp;MARK(rel-&gt;r_offset);<br> &nbsp; &nbsp; &nbsp; &nbsp;TRACE_TYPE(RELO, \"RELO REL32 %08x &lt;- %08x - %08x %s\",<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reloc, sym_addr, rel-&gt;r_offset, sym_name);<br> &nbsp; &nbsp; &nbsp; &nbsp;*reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc) += sym_addr - rel-&gt;r_offset;<br> &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp;case R_ARM_COPY:<br> &nbsp; &nbsp; &nbsp; &nbsp;\/*<br> &nbsp; &nbsp; &nbsp; &nbsp; * ET_EXEC is not supported so this should not happen.<br> &nbsp; &nbsp; &nbsp; &nbsp; *<br> &nbsp; &nbsp; &nbsp; &nbsp; * http:\/\/infocenter.arm.com\/help\/topic\/com.arm.doc.ihi0044d\/IHI0044D_aaelf.pdf<br> &nbsp; &nbsp; &nbsp; &nbsp; *<br> &nbsp; &nbsp; &nbsp; &nbsp; * Section 4.6.1.10 \"Dynamic relocations\"<br> &nbsp; &nbsp; &nbsp; &nbsp; * R_ARM_COPY may only appear in executable objects where e_type is<br> &nbsp; &nbsp; &nbsp; &nbsp; * set to ET_EXEC.<br> &nbsp; &nbsp; &nbsp; &nbsp; *\/<br> &nbsp; &nbsp; &nbsp; &nbsp;DL_ERR(\"%s R_ARM_COPY relocations are not supported\", get_realpath());<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br>#endif<br> &nbsp; &nbsp; &nbsp;default:<br> &nbsp; &nbsp; &nbsp; &nbsp;DL_ERR(\"unknown reloc type %d @ %p (%zu)\", type, rel, idx);<br> &nbsp; &nbsp; &nbsp; &nbsp;return false;<br> &nbsp;  }<br>  }<br> &nbsp;return true;<br>}<\/pre>\n\n\n\n<ul><li>\u8ffd\u6eafaddend() ,\u5982\u679crel\u7c7b\u578b\u4e3aR_ARM_RELATIVE \u6216\u8005R_ARM_IRELATIVE \u5219\u8fd4\u56de\u7b2c\u4e8c\u4e2a\u53c2\u6570\uff0c\u5426\u5219\u8fd4\u56de0.<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {<br> &nbsp;if (ELFW(R_TYPE)(rel-&gt;r_info) == R_GENERIC_RELATIVE ||<br> &nbsp; &nbsp; &nbsp;ELFW(R_TYPE)(rel-&gt;r_info) == R_GENERIC_IRELATIVE) {<br> &nbsp; &nbsp;return *reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc_addr);<br>  }<br> &nbsp;return 0;<br>}<\/pre>\n\n\n\n<ul><li>load_bias_ \u7684\u8ba1\u7b97\u65b9\u6cd5<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">load_bias_ = reinterpret_cast&lt;uint8_t*&gt;(start) - addr;<\/pre>\n\n\n\n<p>start: =<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">start = ReserveAligned(mmap_hint, load_size_, kLibraryAlignment);<\/pre>\n\n\n\n<p>addr : = 0<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,\n                                ElfW(Addr)* out_min_vaddr,\n                                ElfW(Addr)* out_max_vaddr){\n    ......\n    ElfW(Addr) min_vaddr = 0xffffffffffffffff;\n    ElfW(Addr) max_vaddr = 0;\n    \/\/\u904d\u5386\u7a0b\u5e8f\u5934\u8868\u6240\u6709\u7684\u5b57\u6bb5\n    for (size_t i = 0; i &lt; phdr_count; ++i) {\n    const ElfW(Phdr)* phdr = &amp;phdr_table[i];\n\n    if (phdr-&gt;p_type != PT_LOAD) {\n      continue;\n    }\n    found_pt_load = true;\n\n    if (phdr-&gt;p_vaddr &lt; min_vaddr) {\n      min_vaddr = phdr-&gt;p_vaddr;\n    }\n    if (phdr-&gt;p_vaddr + phdr-&gt;p_memsz &gt; max_vaddr) {\n      max_vaddr = phdr-&gt;p_vaddr + phdr-&gt;p_memsz;\n    }\n  }\n  if (!found_pt_load) {\n    min_vaddr = 0;\n  }\n\n  min_vaddr = PAGE_START(min_vaddr);\n  max_vaddr = PAGE_END(max_vaddr);\n    ......\n  if (out_max_vaddr != nullptr) {\n    *out_max_vaddr = max_vaddr;\n  }\n    ......\n}\n\nload_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &amp;min_vaddr);\nuint8_t* addr = reinterpret_cast&lt;uint8_t*&gt;(min_vaddr);<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ \u5982\u679crel\u7c7b\u578b\u4e3aR_ARM_RELATIVE \u6216\u8005R_ARM_IRELATIVE \u5219\u8fd4\u56de\u7b2c\u4e8c\u4e2a\u53c2\u6570\u6307\u5411\u7684\u503c\u3002\nstatic ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {\n  if (ELFW(R_TYPE)(rel-&gt;r_info) == R_GENERIC_RELATIVE ||\n      ELFW(R_TYPE)(rel-&gt;r_info) == R_GENERIC_IRELATIVE) {\n    return *reinterpret_cast&lt;ElfW(Addr)*&gt;(reloc_addr);\n  }\n  return 0;\n}<\/pre>\n\n\n\n<p>\u91cd\u5b9a\u4f4d\u7684\u7c7b\u578b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#define R_GENERIC_JUMP_SLOT R_ARM_JMP_SLOT \/\/\u7528\u4e8e\u63d0\u4f9b\u5ef6\u8fdf\u7ed1\u5b9a\u3002\u6b64\u91cd\u5b9a\u4f4d\u504f\u79fb\u6210\u5458\u53ef\u6307\u5b9a\u8fc7\u7a0b\u94fe\u63a5\u8868\u9879\u7684\u4f4d\u7f6e\u3002\u8fd0\u884c\u65f6\u94fe\u63a5\u7a0b\u5e8f\u4f1a\u4fee\u6539\u8fc7\u7a0b\u94fe\u63a5\u8868\u9879\uff0c\u4ee5\u5c06\u63a7\u5236\u6743\u8f6c\u79fb\u5230\u6307\u5b9a\u7684\u7b26\u53f7\u5730\u5740\n#define R_GENERIC_GLOB_DAT  R_ARM_GLOB_DAT \/\/\u7528\u4e8e\u5c06 GOT \u9879\u8bbe\u7f6e\u4e3a\u6240\u6307\u5b9a\u7b26\u53f7\u7684\u5730\u5740\n#define R_GENERIC_RELATIVE  R_ARM_RELATIVE \/\/\u6b64\u7c7b\u578b\u7684\u91cd\u5b9a\u4f4d\u9879\u5fc5\u987b\u4e3a\u7b26\u53f7\u8868\u7d22\u5f15\u6307\u5b9a\u503c\u96f6,\u6b64\u91cd\u5b9a\u4f4d\u504f\u79fb\u6210\u5458\u53ef\u6307\u5b9a\u5171\u4eab\u5e93\u4e2d\u5305\u542b\u8868\u793a\u76f8\u5bf9\u5730\u5740\u7684\u503c\u7684\u4f4d\u7f6e<\/pre>\n\n\n\n<p>\u91cd\u5b9a\u4f4d\u8fd0\u7b97\u65b9\u6cd5:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#define R_GENERIC_JUMP_SLOT R_ARM_JMP_SLOT \/\/\n#define R_GENERIC_GLOB_DAT  R_ARM_GLOB_DAT \/\/  \u4fee\u6b63offset\u4e3a\u7b26\u53f7\u5730\u5740\u3002\n#define R_GENERIC_RELATIVE  R_ARM_RELATIVE \/\/ \u91cd\u5b9a\u4f4doffset\u4e3a\u57fa\u5730\u5740 + \u504f\u79fb<\/pre>\n\n\n\n<p>\u9a8c\u8bc1\u91cd\u5b9a\u4f4d\u8fc7\u7a0b\u3002<\/p>\n\n\n\n<p>\u4ee5\u7c7b\u578b\u4e3aR_ARM_RELATIVE \u4e3a\u4f8b\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">offset\t\ttype\n0001a610  00000017 R_ARM_RELATIVE<\/pre>\n\n\n\n<p>\u504f\u79fb\u4e3a1a610 \u7c7b\u578b\u4e3aR_ARM_RELATIVE \uff0c\u8be5\u504f\u79fb\u7684\u503c\u4e3a19758 , \u5219\u4fee\u6b63 base+1a610 \u7684\u5730\u5740\u7684\u503c\u4e3a 19758 + base\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"22\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153913863-1024x22.png\" alt=\"image-20201210153913863\" class=\"wp-image-227\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153913863-1024x22.png 1024w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153913863-300x6.png 300w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153913863-768x16.png 768w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153913863.png 1084w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1005\" height=\"23\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153926488.png\" alt=\"image-20201210153926488\" class=\"wp-image-226\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153926488.png 1005w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153926488-300x7.png 300w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/image-20201210153926488-768x18.png 768w\" sizes=\"(max-width: 1005px) 100vw, 1005px\" \/><\/figure>\n\n\n\n<p>\u91cd\u5b9a\u4f4d\u7ed3\u679c\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">libnative-lib.so RELO RELATIVE 0xcfa22610 &lt;-0xcfa21758  load_bias 0xcfa08000 addend 0x19758 si-&gt;base 0xcfa08000<\/pre>\n\n\n\n<p>\u4f46\u662f\u91cd\u5b9a\u4f4d\u7b97\u6cd5\u89e3\u51b3\u4e86\uff0c\u4f46\u662f\u5bf9\u4e8e\u4e0d\u540c\u7684\u7c7b\u578b\u542b\u4e49\u662f\u4ec0\u4e48\uff1f\uff1f \u53ef\u4ee5\u786e\u5b9aR_ARM_RELATIVE \u5bf9\u5e94\u5185\u90e8\u7b26\u53f7\u91cd\u5b9a\u4f4d \uff0c R_ARM_GLOB_DAT\uff0cR_ARM_JMP_SLOT\u5bf9\u5e94\u5916\u90e8\u7b26\u53f7 \uff0c\u5176\u4e2dR_ARM_GLOB_DAT\u548cR_ARM_JMP_SLOT\u7684\u5dee\u522b\u662f\uff1f\uff1f<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"452\" src=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/20180827111446818-1024x452.png\" alt=\"img\" class=\"wp-image-223\" srcset=\"http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/20180827111446818-1024x452.png 1024w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/20180827111446818-300x133.png 300w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/20180827111446818-768x339.png 768w, http:\/\/pareto.fun\/wp-content\/uploads\/2020\/12\/20180827111446818.png 1080w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\u8fde\u63a5\u8fc7\u7a0b\u7ed3\u675f\u540e\uff0c\u5728\u4f9d\u6b21\u8fd4\u56de\u5230\u4e0a\u5c42\u51fd\u6570\uff0c\u5c31\u53ef\u4ee5\u660e\u767d\u4e00\u4e2aso\u7684\u52a0\u8f7d\u8fc7\u7a0b\u4e3a \u5206\u914d\u7a7a\u95f4-> \u89e3\u6790elf -> \u91cd\u5b9a\u4f4d\u7a7a\u95f4 -> \u8c03\u7528init -> \u5b58\u5728\u5219\u8c03\u7528Jni_Onload .<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u88c5\u8f7dSegment<\/h2>\n\n\n\n<p>bionic\/linker\/linker_phdr.cpp  ElfReader::LoadSegments<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/oss.pareto.fun\/img\/Snipaste_2022-08-12_19-51-11.png\" alt=\"\"\/><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote\"><p><a href=\"https:\/\/docs.oracle.com\/cd\/E19120-01\/open.solaris\/819-0690\/chapter6-26\/index.html\">https:\/\/docs.oracle.com\/cd\/E19120-01\/open.solaris\/819-0690\/chapter6-26\/index.html<\/a> \u91cd\u5b9a\u4f4d\u7c7b\u578b<\/p><p><a href=\"http:\/\/nicephil.blinkenshell.org\/my_book\/ch07s04.html\">http:\/\/nicephil.blinkenshell.org\/my_book\/ch07s04.html<\/a> ELF \u76f8\u5173\u77e5\u8bc6<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>step 0\u9636\u6bb5\uff0c\u521b\u5efa\u4e00\u4e2a\u5217\u8868 &nbsp;\/\/ Step 0: prepare. &nbsp;Lo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[9],"tags":[],"_links":{"self":[{"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/posts\/217"}],"collection":[{"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/pareto.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=217"}],"version-history":[{"count":9,"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/posts\/217\/revisions"}],"predecessor-version":[{"id":415,"href":"http:\/\/pareto.fun\/index.php?rest_route=\/wp\/v2\/posts\/217\/revisions\/415"}],"wp:attachment":[{"href":"http:\/\/pareto.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=217"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/pareto.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=217"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/pareto.fun\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}