musl libc ldso 動態加載研究筆記:02

前言

  • 本篇繼續研究 musl libc ldso 的動態加載過程中遇到的關鍵性的概念:到底要加載ELF 文件的哪些內容到 內存

  • 當前如果遇到 ELF 動態加載,當前系統需要有【文件系統】,并且有較大的內存,因為 ELF 文件是無法直接運行的,首先通過解析 ELF 頭部 獲取入口函數,把需要載入到內存中的文件內容復制到指定內存區域,然后執行ELF 的入口函數,通常不是 ELF的 main 函數,而是更早的執行函數,如 _start 或者 _dlstart 函數。此時 PC 指針指向 ELF 加載的基地址 + ELF 入口函數。

ELF 加載基地址

  • 一個 ELF 文件,是否可以隨意的加載?

當前驗證發現: ELF 文件包括我們通常見到的 可以執行的文件,以及 共享庫(如 xx.so)。共享庫沒有連接地址,基址是 0,但入口函數不一定是 0,如果遇到入口函數也是 0 的,需要注意這個 偏移地址 為 0 的入口函數,是否只是個空的符號,無法執行

  • 為何有的 xxx.so 也稱作 ELF 文件? 比如 musl libc.so,本身是個 庫,但是它 有入口函數,并且可以執行。 當前 musl libc.so 確實如此,通常我們一般區分 執行文件與 庫,庫不用于執行。但是 musl libc.so 具備執行的功能,就像是我們見到的普通的執行文件,但是它依舊具備普通庫的功能,為其他動態編譯的應用程序提供共享庫。

  • 作為 共享庫與可執行 集成在一起的 musl libc.so,基地址:0,入口函數不為0,基地址為0 可以重定位加載,如手動把 libc.so 加載到 0x200000 地址, 那么 libc.so 的入口函數就是: 0x200000 + libc.so 入口地址

  • 普通靜態或者動態鏈接的ELF 文件,由于基地址 不為0,就無法手動加載到 隨意的地址。

  • 如下 ELF 文件:基地址 0x200000,這個基地址跟鏈接腳本中的鏈接地址有關系,可以查看這個 elf 的連接腳本配置

  • 入口點:入口地址,這個地址 已經是基于基地址 0x200000的,所以這個地址就不能隨機加載了。如果想改變 這個 elf 的基地址,需要更改 相應的 鏈接腳本 鏈接地址的設置

在這里插入圖片描述

動態加載需要加載哪些 ELF 內容到內存

  • 有的 ELF 文件特別的大,尤其是開啟了 【DEBUG】的,比如編譯時使用 -O0 -g, gdb 的調試信息都加入 ELF 文件了, ELF 文件不同于單片機的燒寫文件 bin 文件,里面還有一些內容,如調試信息,是不需要加載到內存的,那么到底需要加載什么內容呢?

  • 這部分可以查看 Linux 內核代碼 elf 加載部分,如 linux-6.3.8/fs/binfmt_elf.c 中的 load_elf_binary

  • Linux 系統由于默認支持 mmu,執行文件的 mmap 映射,所以沒有文件沒有使用常規的 內存分配,不過依舊是先把文件內容映射 到用戶地址空間,之所以不填充,是因為 Linux文件mmap 有缺頁異常機制,需要訪問時才會真正載入文件內容到內存,這樣有很多好處,開始只映射(占位子)不加載,這樣節省了加載時間,一個 ELF 文件,不可能上來全部執行到,可能只會執行部分內容,這樣采用 訪問時再加載,將會節省數量可觀的內存,節省大量的加載時間。加上文件 mmap 有 cache 功能,如果加載過后,緩存暫時不清掉,這樣下次執行就不再重復加載了。Linux 這個文件mmap 映射加載機制,對于 ELF 加載非常的有用。

  • 經過熟悉 Linux 的 load_elf_binary ,發現只需要 加載 PT_LOAD

  • 那么 ELF 的 PT_LOAD 段,真的覆蓋 ELF 的所有需要加載到內存中的內容范圍嗎?有沒有漏下的?或者說 elf 不是還有 重定位、符號、.text.data、等等嗎?這些包含在里面嗎?

  • 通過 elf 查看工具,加上對實際加載到內存的內容進行反向 dump 出來,肯定的一點就是: ELF 的 PT_LOAD 段 包含了所有需要加載到內存的文件內容,是所有,如果在其他的系統上,發現動態加載后, 內存中的文件內容不正確,或者部分內容為0,需要查看文件加載部分是否有處理不當的地方。

查看 PT_LOAD

  • 可以使用 Die 這個工具,查看 ELF文件

在這里插入圖片描述

  • 這里了解到, PT_LOAD 段 第一個段 文件偏移是 0,也就是把 ELF 文件頭部也加入了內存

  • 兩個 PT_LOAD 段 的大小:Program 中的 p_filesz 就是當前的段大小,總大小: 0x23528 + 0x9f8 = 0x23f20,之所以這么計算,是因為 當前的兩個段 是連在一起的。

  • 由于段有多個節(section),可以查看 節 信息,

在這里插入圖片描述

  • 通過 計算 PT_LOAD 段的總大小,知道 這個 elf 文件 前面 0 ~ (0x23f20 -1) ,也就是 0x23f20 個字節已經加載到內存,剩下 的節,.bss 沒有實際內容,但內存中需要留位置,并且清 0。其他的節全部是 調試信息 debug 相關的。

  • 所以通過加載 PT_LOAD 段,確實實現了整個 ELF 必需文件內容的全部加載

加載大小

  • 這里需要提一下:段的加載大小,不是 段的 p_filesz,而是 段的 p_memsz, p_memsz 一般等于或者大于 p_filesz,超出的大小,就是 .bss section 的大小,這部分大小需要手動清零,不清零,可能引發程序啟動后的異常,比如定義了一個變量,但是沒有初始化就使用,而程序員默認沒有初始化的變量會被初始化 為 0。 清零 .bss 就是清零 PT_LOAD 段 中 p_memsz - p_filesz 大小的區域,這個區域的起始地址應該是: base +elf_ppnt->p_vaddr + elf_ppnt->p_filesz,如果是靜態連接編譯的 elf 程序, base 是0,也就是 elf_ppnt->p_vaddr + elf_ppnt->p_fileszelf_ppnt->p_vaddr 是這個文件段的起始地址。

  • 這里需要提一下: 段的 p_offset,這個是相對文件本身的偏移,通過情況下, p_offsetp_vaddr 是相同的,但也有不相同的。所以在文件填充時,需要把 文件內容 偏移 p_offset 后,讀取到內存地址 p_vaddr 的位置,也就是說: 文件內容的存放位置 與 文件映射到內存的地址,并非一一對應。

在這里插入圖片描述

小結

  • 本篇注意講解一下 ELF文件在 動態加載時需要加載哪些內容到內存,注意這里的動態加載,是動態加載 ELF 文件,這個 ELF文件,不單是 動態編譯鏈接的 ELF,也包括靜態編譯鏈接的 ELF 以及 經常遇到的 動態共享庫 (xx.so)

  • 需要熟悉 ELF 的 頭部、Program Header、了解 各個 Segment 段,了解 Section 節信息,這樣對理解 動態加載程序,熟悉 動態加載非常有用。

  • 需要了解操作系統的進程、線程機制,文件映射 mmap 機制。注意需要反復確認 內存的文件內容是否正確、完整。可以同 dump 的方式,把內存中的文件內容 dump 成一個文件,然后與實際的文件進行內容對比。

  • 需要深刻了解 文件段的本身的偏移 :p_offset 與 內存地址 p_vaddr 的關系,也需要了解 段真實文件大小 p_filesz 與 p_memsz 的關系,也就是 .bss 節的存在

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43171.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IDEA兩種方法修改生成的jar包名字

方法一&#xff1a; 直接修改pom文件中的如下部分 <artifactId>excelreport</artifactId> <version>0.0.1-SNAPSHOT</version> <name>excelreport</name> <description>excelreport</description> 修改完成后&#xff0c;點…

SpringBoot3集成Kafka

標簽&#xff1a;Kafka3.Kafka-eagle3&#xff1b; 一、簡介 Kafka是一個開源的分布式事件流平臺&#xff0c;常被用于高性能數據管道、流分析、數據集成和關鍵任務應用&#xff0c;基于Zookeeper協調的處理平臺&#xff0c;也是一種消息系統&#xff0c;具有更好的吞吐量、內…

跟著美團學設計模式(感處)

讀了著篇文章之后發現真的是&#xff0c;你的思想&#xff0c;你的思維是真的比比你擁有什么技術要強的。 注 開閉原則 開閉原則&#xff08;Open-Closed Principle&#xff09;是面向對象設計中的基本原則之一&#xff0c;它的定義是&#xff1a;一個軟件實體應該對擴展開放…

python生成旗幟--比如美國國旗生成

目錄 1、解釋說明&#xff1a; 2、使用示例&#xff1a; 3、注意事項&#xff1a; 1、解釋說明&#xff1a; 在Python中&#xff0c;生成國旗可以通過使用第三方庫或者自定義函數來實現。通常&#xff0c;我們可以使用Pillow庫來處理圖像&#xff0c;以及使用matplotlib庫來…

python爬蟲7:實戰1

python爬蟲7&#xff1a;實戰1 前言 ? python實現網絡爬蟲非常簡單&#xff0c;只需要掌握一定的基礎知識和一定的庫使用技巧即可。本系列目標旨在梳理相關知識點&#xff0c;方便以后復習。 申明 ? 本系列所涉及的代碼僅用于個人研究與討論&#xff0c;并不會對網站產生不好…

carla中lka實現(二)

前言&#xff1a; 首先計算之前檢測出來的車道線的中線與輸入圖像的中線進行計算距離&#xff0c;&#xff0c;并設置不同的閾值對于不同的方向進行相關的調整。 一、車輛中心線 一般而言將攝像頭架設在車輛的正中心軸上&#xff0c;所獲得的圖像的中間線極為車輛的中心。 …

QGraphicsView 實例3地圖瀏覽器

主要介紹Graphics View框架&#xff0c;實現地圖的瀏覽、放大、縮小&#xff0c;以及顯示各個位置的視圖、場景和地圖坐標 效果圖: mapwidget.h #ifndef MAPWIDGET_H #define MAPWIDGET_H #include <QLabel> #include <QMouseEvent> #include <QGraphicsView&…

WSL2 ubuntu子系統OpenCV調用本機攝像頭的RTSP視頻流做開發測試

文章目錄 前言一、Ubuntu安裝opencv庫二、啟動 Windows 本機的 RTSP 視頻流下載解壓 EasyDarwin查看本機攝像頭設備開始推流 三、在ubuntu 終端編寫代碼創建目錄及文件創建CMakeLists.txt文件啟動 cmake 配置并構建 四、結果展示啟動圖形界面在圖形界面打開終端找到 rtsp_demo運…

linux系統服務學習(二)linux下yum源配置實戰

文章目錄 Linux下yum源配置實戰一、Linux下軟件包的管理1、軟件安裝方式2、源碼安裝的配置過程3、詳解源碼安裝的配置過程&#xff08;定制&#xff09;4、詳解編譯過程5、安裝過程6、axel多線程下載軟件源碼安裝7、使用軟鏈接解決command not found8、使用環境變量解決command…

軟考A計劃-系統集成項目管理工程師-收尾管理

點擊跳轉專欄>Unity3D特效百例點擊跳轉專欄>案例項目實戰源碼點擊跳轉專欄>游戲腳本-輔助自動化點擊跳轉專欄>Android控件全解手冊點擊跳轉專欄>Scratch編程案例點擊跳轉>軟考全系列點擊跳轉>藍橋系列 &#x1f449;關于作者 專注于Android/Unity和各種游…

字符串的無重復排列組合

題目描述&#xff1a; 無重復字符串的排列組合。編寫一種方法&#xff0c;計算某字符串的所有排列組合&#xff0c;字符串每個字符均不相同。 示例1: 輸入&#xff1a;S "qwe" 輸出&#xff1a;["qwe", "qew", "wqe", "weq&q…

中間件(二)dubbo負載均衡介紹

一、負載均衡概述 支持輪詢、隨機、一致性hash和最小活躍數等。 1、輪詢 ① sequences&#xff1a;內部的序列計數器 ② 服務器接口方法權重一樣&#xff1a;&#xff08;sequences1&#xff09;%服務器的數量&#xff08;決定調用&#xff09;哪個服務器的服務。 ③ 服務器…

opencv直方圖與模板匹配

import cv2 #opencv讀取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方圖 cv2.calcHist(images,channels,mask,histSize,ran…

Spring中Bean的生命周期以及Bean的單例與多例模式

一. Bean的生命周期 bean的生命周期可以表達為&#xff1a;bean的定義?bean的初始化?bean的使用?bean的銷毀 Bean的初始化過程 1&#xff09;通過XML、Java annotation&#xff08;注解&#xff09;以及Java Configuration&#xff08;配置類&#xff09; 等方式加載Bea…

2023+HuggingGPT: Solving AI Tasks with ChatGPT and itsFriends in Hugging Face

摘要&#xff1a; 語言是llm(例如ChatGPT)連接眾多AI模型(例如hugs Face)的接口&#xff0c;用于解決復雜的AI任務。在這個概念中&#xff0c;llms作為一個控制器&#xff0c;管理和組織專家模型的合作。LLM首先根據用戶請求規劃任務列表&#xff0c;然后為每個任務分配專家模…

Unity 鼠標實現對物體的移動、縮放、旋轉

文章目錄 1. 代碼2. 測試場景 1. 代碼 using UnityEngine;public class ObjectManipulation : MonoBehaviour {// 縮放比例限制public float MinScale 0.2f;public float MaxScale 3.0f;// 縮放速率private float scaleRate 1f;// 新尺寸private float newScale;// 射線pri…

【Windows系統編程】03.遠線程注入ShellCode

shellcode&#xff1a;本質上也是一段普通的代碼&#xff0c;只不過特殊的編程手法&#xff0c;可以在任意環境下&#xff0c;不依賴于原有的依賴庫執行。 遠程線程 #include <iostream> #include <windows.h> #include <TlHelp32.h>int main(){HANDLE hPr…

Educational Codeforces Round 153 (Rated for Div. 2)ABC

Educational Codeforces Round 153 (Rated for Div. 2) 目錄 A. Not a Substring題目大意思路核心代碼 B. Fancy Coins題目大意思想核心代碼 C. Game on Permutation題目大意思想核心代碼 A. Not a Substring 題目大意 給定一個只包含“&#xff08;”和“&#xff09;”這兩…

react-native-webview RN和html雙向通信

rn登錄后得到的token需要傳遞給網頁&#xff0c;js獲取到的瀏覽器信息需要傳遞給rn RN Index.js: import React from react import { WebView } from react-native-webview import useList from ./useListexport default function Index(props) {const { uri, jsCode, webVie…

iPhone刪除的照片能恢復嗎?不小心誤刪了照片怎么找回?

iPhone最近刪除清空了照片還能恢復嗎&#xff1f;大家都知道&#xff0c;照片對于我們來說是承載著美好回憶的一種形式。它記錄著我們的平淡生活&#xff0c;也留住了我們的美好瞬間&#xff0c;具有極其重要的紀念價值。 照片不小心誤刪是一件非常難受的事&#xff0c;那么iP…