___ ___ ________ ___ __ ___ ________ ________
|\ \ |\ \|\ ___ \|\ \|\ \ |\ \ |\ __ \|\ __ \
\ \ \ \ \ \ \ \\ \ \ \ \/ /|\ \ \ \ \ \|\ \ \ \|\ /_
\ \ \ \ \ \ \ \\ \ \ \ ___ \ \ \ \ \ __ \ \ __ \
\ \ \____\ \ \ \ \\ \ \ \ \\ \ \ \ \____\ \ \ \ \ \ \|\ \
\ \_______\ \__\ \__\\ \__\ \__\\ \__\ \_______\ \__\ \__\ \_______\
\|_______|\|__|\|__| \|__|\|__| \|__|\|_______|\|__|\|__|\|_______|
æ¯äžªçšåºåéœçšè¿éŸæ¥åšïŒäœåŸå°æäººçæ£çè§£å®ã
åšè¿äžªå®éªäžïŒäœ å°äº²æå®ç°äžäžªéŸæ¥åšïŒæåŒçšåºæ¯åŠäœè¢«ãæŒæ¥ãåšäžèµ·çç§å¯ãæä»¬è®Ÿè®¡äºäžäžªå奜çç®æ æä»¶æ ŒåŒïŒFLEïŒïŒè®©äœ å¯ä»¥äžæ³šäºçè§£éŸæ¥çæ žå¿æŠå¿µã
Warning
è¿æ¯ LinkLab ç第äžäžªçæ¬ïŒå¯èœååšäžäºé®é¢ãåŠæäœ ïŒ
- åç°äº BugïŒè¯·æäº€ Issue
- æä»»äœ QuestionïŒè¯·åšè®šè®ºåºæåº
乿¬¢è¿äœ 积æåäžåŒæºåäœïŒæ¹è¿æ¡æ¶ä»£ç è§£å³ Issueãææ¯äžºååŠä»¬ççè§£æãè¿éšåç衚ç°å¯è¢«è®¡äžºé¢å€çåæ°ã
Note
æ¬å®éªé¢è®¡èæ¶ 7 - 15 äžªå°æ¶ïŒå ·äœæ åµå 䞪äœå·®åŒå¯èœææåºå«ã
éŸæ¥æ¯å°å€äžªç®æ æä»¶ç»åæäžäžªå¯æ§è¡çšåºçè¿çšãåšç°ä»£èœ¯ä»¶åŒåäžïŒæä»¬äžäŒæææä»£ç éœååšäžäžªæä»¶éââè¿æ ·æ¢äžå©äºä»£ç å€çšïŒä¹äžäŸ¿äºå¢éåäœãçžåïŒæä»¬äŒå°çšåºåè§£æå€äžªæºæä»¶ïŒåå«çŒè¯æç®æ æä»¶ïŒåéè¿éŸæ¥åšå°å®ä»¬ãæŒæ¥ãåšäžèµ·ã
éŸæ¥åšçäž»èŠå·¥äœå æ¬ïŒ
- 笊å·è§£æïŒå°ä»£ç äžç笊å·ïŒåŠåœæ°è°çšãå šå±åéïŒäžå®ä»¬çå®ä¹å¯¹åºèµ·æ¥
- éå®äœïŒè°æŽç¬Šå·çå°åïŒç¡®ä¿çšåºåšå åäžæ£ç¡®è¿è¡
- åžå±è§åïŒåç宿å䞪éšååšå åäžçäœçœ®ïŒå¹¶è®Ÿçœ®éåœçè®¿é®æé
è¿äžªè¿çšç䌌ç®åïŒäœå®é äžæ¶å讞å€å€æçç»èïŒåŠäœå€ç笊å·å²çªïŒåŠäœä¿®æ£ç®æ å°åïŒåŠäœä¿æ€ä»£ç äžè¢«ç¯¡æ¹ïŒåšè¿äžªå®éªäžïŒäœ å°äº²æå®ç°è¿äºåèœïŒæ·±å ¥çè§£ç°ä»£çšåºæ¯åŠäœè¢«ç»è£ èµ·æ¥çã
- æäœç³»ç»ïŒLinuxïŒæšè Ubuntu 22.04 ææŽé«çæ¬ïŒ
- Windows çšæ·å¯èèäœ¿çš WSL 2
- çŒè¯åšïŒæ¯æ C++17
- g++-8 å以äžïŒæšèäœ¿çšææ°çæ¬
- clang çèŸæ°çæ¬
- Python 3.6+
- Make, Git
è¯·äœ¿çš Git 管çäœ ç代ç ïŒå »æç»åžžæäº€çå¥œä¹ æ¯ã
# å
éä»åºïŒè¯·å° your-assignment-repo-url æ¿æ¢äžºäœ çä»åºå°åïŒ
git clone your-assignment-repo-url
cd your-assignment-repo-name
# æå»ºé¡¹ç®
make
# è¿è¡æµè¯ïŒæ€æ¶åºè¯¥äŒå€±èŽ¥ïŒè¿æ¯æ£åžžçïŒ
make test_1 # è¿è¡ä»»å¡äžçæµè¯
make test # è¿è¡æææµè¯LinkLab-2024/
âââ include/ # 倎æä»¶
â âââ fle.hpp # FLE æ ŒåŒå®ä¹ïŒè¯·ä»ç»é
读ïŒ
âââ src/
â âââ base/ # åºç¡æ¡æ¶ïŒå©ææäŸïŒ
â â âââ cc.cpp # çŒè¯åšå端ïŒçæ FLE æä»¶
â â âââ exec.cpp # çšåºå 蜜åšïŒè¿è¡çæççšåº
â âââ student/ # äœ éèŠå®æç代ç
â âââ nm.cpp # ä»»å¡äžïŒç¬Šå·è¡šæ¥çåš
â âââ ld.cpp # ä»»å¡äº~å
ïŒéŸæ¥åšäž»çšåº
âââ tests/ # æµè¯çšäŸ
âââ cases/ # æä»»å¡åç±»çæµè¯
âââ 1-nm-test/ # ä»»å¡äžïŒç¬Šå·è¡šæŸç€º
âââ 2-single-file/ # ä»»å¡äºïŒåºç¡éŸæ¥
âââ ... # æŽå€æµè¯çšäŸ
âââ common/ # æµè¯çšäŸçå
Œ
±åº
âââ minilibc.c # è¿·äœ libc çå®ç°
æ¯äžªä»»å¡éœé æå®æŽçæµè¯çšäŸïŒå æ¬ïŒ
- æºä»£ç ïŒçšäºçææµè¯èŸå ¥
- ææèŸåºïŒçšäºéªè¯äœ çå®ç°
- é 眮æä»¶ïŒå®ä¹æµè¯åæ°
äœ å¯ä»¥ïŒ
- é 读æµè¯ä»£ç äºè§£å ·äœèŠæ±
- è¿è¡æµè¯æ£æ¥å®ç°æ¯åŠæ£ç¡®
- çŒåæ°çæµè¯çšäŸæ¥æ¢çŽ¢æŽå€å¯èœæ§
Linux äœ¿çš ELF æ ŒåŒæ¥ç»ç»åååšå¯æ§è¡æä»¶ãç®æ æä»¶åå ±äº«åºïŒé垞区倧åçµæŽ»ãç¶èïŒè¿ç§æ ŒåŒå¹¶äžæ¯é¢å人类å¯è¯»è讟计çïŒå®ç衚蟟圢åŒåéå«ç倧éçç¢ç»è对äºååŠè èèšææå€§çè®€ç¥ææ¬ã䞺äºè®©äœ äžæ³šäºéŸæ¥çæ žå¿æŠå¿µïŒæä»¬éæ°è®Ÿè®¡äº FLE (Friendly Linking Executable) ïŒæäŸäžç§æŽå¹³åŠãæŽäººç±»åå¥œåæŽç¬Šåè¡äžºå±éšæ§ååïŒLocality of Bahaviour PrincipleïŒçæ ŒåŒã
ä»¥äžæ¯äžäžªç®åçäŸåïŒå±ç€ºäº C 代ç åå ¶çŒè¯åçç®æ æä»¶å 容ïŒäœæ¯ FLE æ ŒåŒïŒïŒ
// test.c
int message[2] = {1, 2}; // å
šå±æ°ç»
static int helper(int x) { // éæåœæ°
return x + message[0];
}
int main() { // çšåºå
¥å£
return helper(42);
}éè¿ ./cc test.c -o test.oïŒå¯çæ test.fle å
容åŠäžïŒ
{
"type": ".obj", // è¿æ¯äžäžªç®æ æä»¶
"shdrs": [
// å䞪èçå
æ°æ®
{
"name": ".text", // èå
"type": 1, // èç±»å
"flags": 1, // èæé
"addr": 0, // èåšå
åäžçèµ·å§å°å
"offset": 0, // èåšæä»¶äžçåç§»é
"size": 36 // èç倧å°
},
{
"name": ".data",
"type": 1,
"flags": 1,
"addr": 0,
"offset": 36,
"size": 8
},
{
"name": ".bss",
"type": 8,
"flags": 9,
"addr": 0,
"offset": 44,
"size": 0
}
],
".text": [
"ð·ïž: helper 20 0", // å±éšç¬Šå·
"ð¢: 55 48 89 e5 89 7d fc 8b 15", // æºåšç
"â: .rel(message - 4)", // éèŠéå®äœ
"ð¢: 8b 45 fc 01 d0 5d c3", // æºåšç
"ð€: main 16 20", // å
šå±ç¬Šå·
"ð¢: 55 48 89 e5 bf 2a 00 00 00 e8 de ff ff ff 5d c3" // æºåšç
],
".data": [
"ð€: message 8 0", // å
šå±ç¬Šå·
"ð¢: 01 00 00 00 02 00 00 00" // æ°æ®
],
".bss": []
}FLE 䜿çšè¡šæ ç¬Šå·æ¥æ è®°äžåç±»åçä¿¡æ¯ïŒ
- æºåšç
åè åè åè ...ð¢ - 笊å·
笊å·å å€§å° èå åç§»é
- æä»¶å éšçå±éšç¬Šå· ð·ïž
- å¯ä»¥è¢«å ¶ä»æä»¶åŒçšçå šå±ç¬Šå·ïŒåŒºç¬Šå·ïŒ ð€
- å¯ä»¥è¢«èŠççå šå±åŒ±ç¬Šå· ð
- éå®äœ
éå®äœç±»å(ç®æ 笊å·å [+/-] éå åŒ)â
è¿äºä¿¡æ¯åšå
åäžçš C++ ç»æäœ FLEObject 衚瀺ïŒå®ä¹åš include/fle.hpp äžïŒïŒ
struct FLEObject {
std::string name; // Object name
std::string type; // ".obj" or ".exe"
std::map<std::string, FLESection> sections; // Section name -> section data
std::vector<Symbol> symbols; // Global symbol table
std::vector<ProgramHeader> phdrs; // Program headers (for .exe)
std::vector<SectionHeader> shdrs; // Section headers
size_t entry = 0; // Entry point (for .exe)
};
struct FLESection {
std::vector<uint8_t> data; // Section data (stored as bytes)
std::vector<Relocation> relocs; // Relocation table for this section
bool has_symbols; // Whether section contains symbols
};
// âŠæä»¬çå®éªæ¡æ¶äŒèªåšå°ç£çäžç FLE æ ŒåŒæä»¶å 蜜䞺å
åäžçç»æäœ FLEObjectïŒè¿äžªè¿çšä¹å«ååºååãåšå®ç°éŸæ¥åšæ¶ïŒäœ å¯èœæŽå€éèŠå
³æ³š FLEObjectïŒFLE æ ŒåŒæä»¶äž»èŠæ¯äžºäºæ¹äŸ¿æ¥çåè°è¯ã
Important
FLE æ ŒåŒæä»¶å FLEObject 倧éšåå
容æ¯å¯¹åºçïŒäœåšæäºæ°æ®çè¡šç€ºäžææäžåãå
·äœæ¥è¯ŽïŒ
- åš FLE æ ŒåŒæä»¶äžïŒéå®äœå笊å·å®ä¹æ¯å
èçã笊å·å®ä¹çå°æ¹çŽæ¥çš ð€ / ð / ð·ïž æ è®°ïŒèåš
FLEObjectäžïŒç¬Šå·è¡šæ¯ç¬ç«çïŒå 嫿¯äžªç¬Šå·åå ¶å®ä¹äœçœ®çä¿¡æ¯ïŒå¹¶äžæ¯äžªFLESectionäžæç¬ç«çéå®äœè¡šã - åš FLE æ ŒåŒæä»¶äžïŒéèŠéå®äœçå°æ¹çŽæ¥çš â å
èæ è®°ïŒäžååšå äœç 0 åèïŒèåšæ¯äžª
FLESectionçdataåæ®µäžïŒéèŠéå®äœçå°æ¹äŒçš 0 å äœã
åšæ¥äžæ¥çä»»å¡äžïŒäœ å°éæ¥å®ç°å€çè¿ç§æ ŒåŒçå·¥å ·éŸïŒä»æåºæ¬ç笊å·è¡šæ¥çåšåŒå§ïŒæç»å®ç°äžäžªå®æŽçéŸæ¥åšã
åå€å¥œäºåïŒè®©æä»¬åŒå§ç¬¬äžäžªä»»å¡ïŒ
äœ ææ²¡æéå°è¿è¿æ ·çé误ïŒ
undefined reference to `printf'
multiple definition of `main'
è¿äºéœäžç¬Šå·ïŒsymbolïŒæå ³ã笊å·å°±åçšåºäžç"åå"ïŒä»£è¡šäºåœæ°ãåéçã让æä»¬éè¿äžäžªäŸåæ¥çè§£ïŒ
static int counter = 0; // éæåéïŒæä»¶å
å¯è§
int shared = 42; // å
šå±åéïŒå
¶ä»æä»¶å¯è§
extern void print(int x); // å€éšåœæ°ïŒéèŠå
¶ä»æä»¶æäŸ
void count() { // å
šå±åœæ°
counter++; // 访é®éæåé
print(counter); // è°çšå€éšåœæ°
}è¿æ®µä»£ç äžå å«äºå ç§äžåç笊å·ïŒ
counterïŒéæç¬Šå·ïŒåªåšæä»¶å å¯è§sharedïŒå šå±ç¬Šå·ïŒå¯ä»¥è¢«å ¶ä»æä»¶åŒçšprintïŒæªå®ä¹ç¬Šå·ïŒéèŠåšéŸæ¥æ¶æŸå°countïŒå šå±åœæ°ç¬Šå·
äœ ç第äžäžªä»»å¡æ¯è¡¥å
src/student/nm.cpp äžç FLE_nm åœæ°ïŒå®ç°äžäžªå·¥å
·æ¥æ¥çè¿äºç¬Šå·ã
对äºäžé¢ç代ç ïŒå®åºè¯¥èŸåºäžè¡äžåä¿¡æ¯ïŒ
0000000000000000 T count # å
šå±åœæ°åš .text è
0000000000000000 b counter # éæåéåš .bss è
0000000000000000 D shared # å
šå±åéåš .data è
æ¯äžåçå ·äœå«ä¹æ¯ïŒ
- å°åïŒç¬Šå·åšå ¶æåšèäžçåç§»é
- ç±»åïŒç¬Šå·çç±»ååäœçœ®
- 倧åïŒTãDãBãRïŒïŒå šå±ç¬Šå·ïŒåå«è¡šç€ºåšä»£ç æ®µãæ°æ®æ®µãBSS 段ãåªè¯»æ°æ®æ®µ
- å°åïŒtãdãbãrïŒïŒå±éšç¬Šå·ïŒåå«è¡šç€ºåšä»£ç æ®µãæ°æ®æ®µãBSS 段ãåªè¯»æ°æ®æ®µ
- WãVïŒåŒ±ç¬Šå·ïŒåå«è¡šç€ºåšä»£ç 段ãè¿æ¯åšæ°æ®æ®µæ BSS 段
- åç§°ïŒç¬Šå·çåå
èŠå®ç°è¿äžªå·¥å ·ïŒäœ éèŠéå笊å·è¡šïŒç¡®å®æ¯äžªç¬Šå·çç±»åïŒå¹¶ææ ŒåŒæå°ä¿¡æ¯ã
Tip
æ ŒåŒåèŸåºå¯ä»¥äœ¿çš:
std::cout << std::setw(16) << std::setfill('0') << std::hex << addr; // C++ 飿 Œæ
printf("%016lx", addr); // C 飿 Œ,èŸåº16äœçåå
è¿å¶æ°,巊䟧补0以åïŒåš C++ 20 åïŒstd::format å std::print æäŸäºæŽç®æŽçæ ŒåŒåæ¹æ¡ïŒæ¬å®éªäœ¿çš -std=c++17 çŒè¯é项ïŒäžæ¯ææ€ç¹æ§ãæ€æ¹æ¡ä»
äŸäºè§£ïŒ
std::print("{:016x}", addr); // Modern C++ 飿 ŒTip
äœ å¯ä»¥æ ¹æ®ç¬Šå·ç section åæ®µå€æå ¶äœçœ®:
- ".text" - ä»£ç æ®µ
- ".data" - æ°æ®æ®µ
- ".bss" - BSS段
- "" (empty) - æªå®ä¹ç¬Šå·
- äœ åºè¯¥åš
FLE_nmçèŸåºäžïŒå¿œç¥æææªå®ä¹ç¬Šå·
- äœ åºè¯¥åš
宿åïŒè¿è¡æµè¯æ¥éªè¯ïŒ
make test_1让æä»¬ä»äžäžªç®åçäŸååŒå§çè§£éŸæ¥åšçå·¥äœåçãå讟æè¿æ ·äžäžªçšåºïŒ
// foo.c
const char str[] = "Hello, World!"; // äžäžªå
šå±å笊䞲垞é
// main.c
extern const char str[]; // 声æïŒstr åšå«å€å®ä¹
void _start()
{
int ans = 0;
for (int i = 0; i < 10; i++) {
ans += str[i]; // éèŠæŸå° str çå®é
äœçœ®
}
// ... éåºç³»ç»è°çš ...
}çŒè¯åšäŒå°è¿äºæºæä»¶çŒè¯æç®æ æä»¶ã
å€ä¹ äžä»»å¡é¶çå
å®¹ïŒæä»¬æäž€ç§çä»·æ¹åŒæ¥è¡šèŸŸè¿äžªç®æ æä»¶ïŒäžç§æ¯ç£çäžç FLE æ ŒåŒæä»¶ïŒäžç§æ¯å
åäžç FLEObject ç»æäœã
以 foo.fle 䞺äŸïŒå®åšç£çäžçæ ŒåŒæä»¶æ¯ïŒ
{
"type": ".obj",
"shdrs": [ /* ... è倎ïŒç¥ïŒ ... */ ],
".text": [],
".rodata": [
"ð€: str 14 0", // å®ä¹äžäžªå
šå±ç¬Šå· strïŒå€§å°äžº 14 åè
"ð¢: 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 00" // "Hello, World!" çåè衚瀺
]
}åœè¿äžªæä»¶è¢«å 蜜å°å
åæ¶ïŒå®äŒè¢«è§£ææäžäžª FLEObject ç»æãåŠäžææè¿°ïŒå
¶äžç symbols æåæ¯äžç³»å Symbol ç»æçåè¡šïŒæ¯äžª Symbol ç»æååšç笊å·åå
¶å®ä¹äœçœ®çä¿¡æ¯ãåšäžäŸäžïŒå讟æä»¬çš obj æ¥è¡šç€ºè¿äžª FLEObjectïŒé£ä¹ obj.symbols[0] æ¯ïŒ
Symbol {
.type = SymbolType::GLOBAL, // å¯¹åºæä»¶äžç ð€
.section = ".rodata", // ç¬Šå·æåšçèæ¯åªè¯»æ°æ®æ®µ
.offset = 0, // åšèå
çåç§»
.size = 14, // 笊å·å€§å°äžº 14 åè
.name = "str" // 笊å·åç§°
}宿¬èŽšäžæ¯åšè¯ŽïŒç¬Šå· str 对åºé£ä¹äžäžªæå .rodata+0 è³ .rodata+14 çãæéãã
è¿äžª FLEObject äžïŒè¿æäžª sections æåïŒæ¯äžç³»å FLESection ç»æçå衚ïŒå
¶äžå
å«äºäžäžªå¯¹åº .rodata èç FLESection 对象ïŒå³ obj.sections[".rodata"]ãè¿æ ·ïŒæä»¬å°±çå°äº Symbol 对象 str ææåçå
·äœå
容ïŒ
FLESection {
.data = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57,
0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00 } // "Hello, World!"
}ä»¥äžæ¯ foo.fle ç®æ æä»¶ç䞀ç§è¡šç€ºïŒç±»äŒŒå°ïŒå¯¹äº main.fleïŒå
¶ç£çäžçæ ŒåŒæä»¶äžºïŒ
{
"type": ".obj",
"shdrs": [
{
"name": ".text",
"type": 1,
"flags": 1,
"addr": 0,
"offset": 0,
"size": 32
},
// å
¶ä»èïŒç¥ïŒ
],
".text": [
"ð€: _start 32 0", // å®ä¹äžäžªå
šå±ç¬Šå· _start
"ð¢: 31 c0 31 d2 0f be 88", // æºåšç
"â: .abs32s(str + 0)", // éèŠéå®äœïŒå¡«å
¥ str çå°å
"ð¢: 48 ff c0 01 ca 48 83 f8 0a 75 ee 89 d7 b8 3c 00",
"ð¢: 00 00 0f 05 c3"
],
// å
¶ä»èïŒç¥ïŒ
}åæ ·ïŒåš FLEObject äžïŒæ¯äžª FLESection 对象éœè¿äžæ¥æäžäžª relocations æåïŒå®æ¯äžç³»å Relocation ç»æçåè¡šãæ¯åŠïŒ
obj.sections[".text"].relocations[0] æ¯ïŒ
Relocation {
.type = RelocationType::R_X86_64_32S, // 32äœæç¬Šå·ç»å¯¹å¯»å
.offset = 7, // éå®äœåšèå
çäœçœ®
.symbol = "str", // ç®æ 笊å·
.addend = 0 // åç§»é
}è¿æ¬èŽšäžæ¯åšè¯ŽïŒæé£ä¹äžäžªæå .text+7 è³ .text+11 çãæéãïŒå
¶åŒéèŠè¢«ä¿®æ£äžºç¬Šå· str çå°åã
éŸæ¥åšåªåäžä»¶äºïŒåžå±è§åïŒç¬Šå·è§£æïŒéå®äœïŒ
æåè¿èŠçæå¯æ§è¡æä»¶ã
éŠå
ïŒéŸæ¥åšå°åäžªç®æ æä»¶äžççžåèïŒ.textã.rodata çïŒåå¹¶ïŒåœ¢æäžäžªæç»çå
ååžå±ã
Tip
åšæ¬ä»»å¡äžïŒäœ å¯ä»¥å
éæ©ç®åå°å°ææç®æ æä»¶çææèéœæé¡ºåºåå¹¶å°äžäžª .load èäžïŒèäžæ¯çæ .textã.rodata çèãå¹¶èµäºå®ä»¬äžåçæé ââ èå犻æ¯ä»»å¡å
çå
容ã
åšèåå¹¶åïŒéŸæ¥åšéèŠæŸå°æ¯äžªç¬Šå·çå®ä¹ïŒææ¯äžªç¬Šå·å ³èå°åå¹¶åçå ååžå±äžãä¹å°±æ¯è®°åœäžæ¯äžªç¬Šå·éœå»äºåªéïŒè¿æ ·äœ åšéå®äœæ¶æèœæŸå°å®ã
Tip
äœ å¯ä»¥çš 0x400000 äœäžºçšåºçåºåïŒæææ¯ïŒ.load 段åšè¿è¡æ¶å°è¢«å èœœå° 0x400000ã
è¿æ ·ïŒåŠæäœ å·²ç»æ main.fle äžå€§å°äžº 32 ç .text èåå¹¶è¿ .load 段äºïŒæ¥äžæ¥äœ èŠåå¹¶ foo.fle ç .data èïŒè¿äžªèåšè¿è¡æ¶çèµ·å§å°åå°±åºè¯¥æ¯ 0x400020ãä»èïŒåšè¿äžªèäžå®ä¹ç offset 䞺 0 çç¬Šå· str çå°å䞺 0x400020ã
Tip
äœ å¯ä»¥èŸ¹åå¹¶èïŒèŸ¹å笊å·è§£æãæ¯åŠïŒäœ å¯ä»¥åå¹¶å®æäžªç®æ æä»¶çæäžªèåïŒæŸå°åšè¿äžªèäžå®ä¹ç笊å·ïŒææ¯äžªç¬Šå·ç offset åæ®µïŒè®Ÿçœ®äžºå®åšåå¹¶åçæ°äœçœ®ïŒå¹¶ææ¯äžªæŽæ°åç Symbol éœå å
¥å°å
šå±ç¬Šå·è¡šäžã
Important
åšå€çç®æ æä»¶ç笊å·è¡šæ¶ïŒäœ äŒåç°åäžªç®æ æä»¶ç笊å·è¡šäžå¯èœå 嫿ªå®ä¹ç¬Šå·ïŒå³åšåœåæä»¶äžè¢«åŒçšäœå°æªå®ä¹ç笊å·ïŒãè¿äžæ å ELF æ ŒåŒçè¡äžºæ¯äžèŽçãå€çè¿äºç¬Šå·æ¶ïŒ
- äžèŠç«å³æ¥åæªå®ä¹é误
- åšåç»çç®æ æä»¶äžç»§ç»æ¥æŸè¯¥ç¬Šå·çå®ä¹
- åªæåšå€ç宿æç®æ æä»¶åïŒä»ç¶æŸäžå°å®ä¹æ¶ææ¥é
åŸå°å šå±ç¬Šå·è¡šåïŒéŸæ¥åšéèŠéåææçéå®äœé¡¹ïŒæ ¹æ®éå®äœé¡¹çç±»åïŒè®¡ç®èŠå¡«å ¥çåŒïŒæŽæ°éå®äœé¡¹ææåçå°ååŒçšã
Tip
éå®äœç±»åå³å®äºåŠäœè®¡ç®èŠå¡«å ¥çåŒã
åšæ¬ä»»å¡äžïŒäœ åªéèŠå€ç R_X86_64_32 å R_X86_64_32S ç±»åçéå®äœ ââ å®ä»¬éœæ¯çŽæ¥å°ç¬Šå·çç»å¯¹å°åå¡«å
¥éå®äœäœçœ®ïŒå³ç»å¯¹éå®äœã
Note
R_X86_64_32 å R_X86_64_32S éœäŒå° 64 äœå°åæªæäžº 32 äœïŒåºå«åšäºéŸæ¥åšåŠäœéªè¯è¿äžªæªææ¯åŠåæ³ïŒ
R_X86_64_32ïŒèŠæ±æªææçé« 32 äœå¿ 须䞺 0ïŒè¿æ ·éè¿é¶æ©å±å¯ä»¥è¿ååºåå§ç 64 äœåŒR_X86_64_32SïŒèŠæ±é« 32 äœçåŒäžæªæåç笊å·äœïŒå³ç¬¬ 32 äœïŒçžåïŒå š 0 æå š 1ïŒïŒè¿æ ·æèœéè¿ç¬Šå·æ©å±è¿ååºåå§ç 64 äœåŒ
äœ å¯ä»¥ç®åå°å¿œç¥å®ä»¬ä¹éŽçåºå«ã
ä»ä»¥äžè¿°ç main.fle 䞺äŸïŒå¯¹äºéå®äœé¡¹ â: .abs32s(str + 0)ïŒç±»å䞺 R_X86_64_32SïŒä»£è¡š text+7 è³ text+11 è¿æ®µç©ºéŽçåŒéèŠè¢«ä¿®æ£äžº str çå°åïŒè¿éç + 0 没æä»ä¹æä¹ïŒéå åŒäžéçšäºç»å¯¹éå®äœïŒïŒéŸæ¥åšéèŠïŒ
-
åšåå¹¶åçå šå±ç¬Šå·è¡šäžæ¥æŸ
str笊å·ïŒè·å笊å·å°å0x400020 -
计ç®èŠå¡«å ¥çåŒ
- 对äº
R_X86_64_32Séå®äœç±»åïŒå³çŽæ¥æªæç¬Šå·å°åçäœ 32 äœ
$$ \text{æç»åŒ} = \text{笊å·å°å} \mathbin{\&} 0xFFFFFFFF = 0x400020 \mathbin{\&} 0xFFFFFFFF = 0x400020 $$ - éªè¯ïŒè¿äžªæªæåçåŒæ¯åæ³çïŒéè¿é¶æ©å±å¯ä»¥è¿ååºåå§ç 64 äœåŒ
- 对äº
-
å°
0x400020å¡«å ¥text+7è³text+11è¿æ®µç©ºéŽïŒåŸå°20 00 40 00ã
Tip
- 泚æåèåºçé®é¢ãx86-64 䜿çšå°ç«¯åºã
- 泚æèŠå äžåºå°åã
æåïŒçæå¯æ§è¡æä»¶ïŒå¡«åæä»¶å€Žã段信æ¯çã
åšæä»¬çæ¡æ¶äžïŒéŸæ¥åšéèŠå建äžäžª .type == ".exe" ç FLEObjectãå
¶ .name åæ®µå¯è®Ÿçœ®äžºä»»æå笊䞲ïŒåŠ "a.out"ïŒïŒ.phdrs åæ®µéèŠè®Ÿçœ®äžºäžäžªæ£ç¡®ç ProgramHeader ç»æïŒä»¥äŸ¿å 蜜åšèœå€æ£ç¡®å°å 蜜çšåºã
Note
å 蜜åšïŒloaderïŒæ¯æäœç³»ç»çäžéšåïŒèŽèŽ£æå¯æ§è¡æä»¶å 蜜å°å åïŒæ¯åŠåé 空éŽãå»ºç«æ å°å ³ç³»ïŒïŒå¹¶åå§åçšåºçæ§è¡ç¯å¢ïŒæ¯åŠåå§åæ 空éŽã跳蜬å°çšåºå ¥å£ç¹ïŒã
æä»¬å®ç°äºäžäžªçšæ·æçå 蜜åšïŒæš¡ææäœç³»ç»å 蜜åšçè¡äžºãéè¿ ./exec åœä»€ïŒäœ å¯ä»¥å 蜜è¿è¡äžäžª FLE æ ŒåŒç坿§è¡æä»¶ã
äœ å°åšäžåŠæ ICS 2 诟çšäžåŠå°æå ³å 蜜åšçæŽå€ç¥è¯ã
Tip
äžé¢æå°ïŒæä»¬åšè¿äžªä»»å¡äžå¯ä»¥æææèäžè¡èå°æè¿ .load 段éãæä»¬éèŠæ·»å äžäžªçšåºå€Žæ¥æè¿°è¿äžªæ®µïŒäœ å¯ä»¥çŽæ¥åèäžé¢è¿æ®µä»£ç ïŒ
ProgramHeader header = {
.name = ".load", // æè¿°çæ¯ .load 段
.vaddr = 0x400000, // æä»¬äœ¿çšåºå®çå 蜜å°å 0x400000
.size = size, // åå¹¶åçæ»å€§å°
.flags = PHF::R | PHF::W | PHF::X // å¯è¯»ãå¯åã坿§è¡ïŒç®åå°èµäºæææé
};æ€å€ïŒå¯æ§è¡æä»¶å¿
é¡»æå®äžäžªå
¥å£ç¹ïŒentry pointïŒïŒä¹å°±æ¯çšåºåŒå§æ§è¡çäœçœ®ã
ææ¯äŸïŒåšåºäº C è¯èšåŒåççšåºäžïŒè¿äžªå
¥å£ç¹éåžžæ¯å䞺 _start çåœæ°ãéŸæ¥åšéèŠåšåå¹¶çå
šå±ç¬Šå·è¡šäžæŸå° _start 笊å·ïŒå¹¶å°å
¶å°åïŒåºå°å + 笊å·åç§»ïŒè®Ÿçœ®äžºçšåºçå
¥å£ç¹ã
åšå®æè¿äºå·¥äœåïŒæä»¬å°±åŸå°äºäžäžªå®æŽç FLEObject ç»æäœïŒäžºå èœœåšæè¿°äºæŽäžªçšåºçåºèŸŸæçå
ååžå±ã
FLE_ld åœæ°åªéè¿åè¿äžªç»æäœïŒæä»¬çå®éªæ¡æ¶äŒå°å
¶åºåå䞺 FLE æ ŒåŒæä»¶ïŒ
{
"type": ".exe", // 衚æè¿æ¯äžäžªå¯æ§è¡æä»¶
"phdrs": [
{
"name": ".load", // çšåºå€Ž
"vaddr": 4194304, // åºå®çå 蜜å°å 0x400000
"size": 46, // åå¹¶åçæ»å€§å°
"flags": 7 // å¯è¯»ãå¯åã坿§è¡
},
],
"entry": 4194304, // çšåºçå
¥å£ç¹ 0x400000 çåè¿å¶è¡šç€º
".load": [ // åå¹¶åçèå
容ïŒåªå
嫿ºåšç
"ð¢: 31 c0 31 d2 0f be 88 20 00 40 00 48 ff c0 01 ca",
"ð¢: 48 83 f8 0a 75 ee 89 d7 b8 3c 00 00 00 0f 05 c3",
"ð¢: 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 00"
]
}è¿æ ·æä»¬å°±åŸå°äºäžäžªå®æŽç坿§è¡æä»¶ã
Tip
åšå®ç°éŸæ¥åšçè¿çšäžïŒäžç§å¯è¡çæè·¯æ¯éçšå€éæ«æçæ¹æ³ïŒ
- ç¬¬äžæ¬¡æ«æïŒåå¹¶ææèçå 容
- ç¬¬äºæ¬¡æ«æïŒæ¶éå¹¶è§£æææç¬Šå·
- ç¬¬äžæ¬¡æ«æïŒä»äžå°äžäŸæ¬¡å€çææéå®äœé¡¹ïŒå°è®¡ç®åºçå°ååå¡«
æåçæçšåºå€ŽïŒå¹¶è®Ÿçœ®å
¥å£ç¹ïŒåŸå°æç»ç FLEObjectã
å¯ä»¥æèïŒäžºä»ä¹èŠéåè¿æ ·çæ«æé¡ºåºïŒææ²¡æå ¶ä»æŽå¥œçæ¹æ³ïŒ
è¯·åš src/student/ld.cpp äžå®ç°äœ çéŸæ¥åšã
Tip
Start simple, move fast!
åšå®ç°è¿çšäžïŒäœ å¯ä»¥å
å€çåªæäžäžªèŸå
¥æä»¶çç®åæ
圢ãäœ¿çš readfle å·¥å
·æ£æ¥èŸåºæä»¶çæ ŒåŒæ¯åŠæ£ç¡®å¹¶æå°è°è¯ä¿¡æ¯ïŒæ¯åŠèçåå¹¶è¿çšã笊å·çæ°å°åãéå®äœçå€çè¿çšïŒä¹äŒå¯¹è°è¯åŸæåž®å©ãåè§è°è¯æåã
宿åïŒäœ çéŸæ¥åšå°±èœå€çåºæ¬çéŸæ¥ä»»å¡äºãè¿è¡æµè¯æ¥éªè¯ïŒ
make test_2åšä»»å¡äºäžïŒæä»¬å€çäºç»å¯¹éå®äœââ访é®å šå±åéæ¶äœ¿çšç»å¯¹å°åæéèŠçéå®äœãåœæ°è°çšåææäžåïŒæ£åŠæä»¬åšæ±çŒäžç« æåŠå°çïŒå¯¹åºæ±çŒçº§å«ççžå¯¹è·³èœ¬ïŒåšéŸæ¥æ¶åéèŠåçžå¯¹éå®äœã
让æä»¬çäžäžªäŸåïŒ
// lib.c
int add(int x) { // äžäžªç®åçåœæ°
return x + 1;
}
// main.c
extern int add(int); // 声æïŒadd åœæ°åšå«å€å®ä¹
int main() {
return add(41); // è°çš add åœæ°
}çŒè¯åšäŒå°è¿äºæºæä»¶çŒè¯æç®æ æä»¶ãè¿äžªåœæ°è°çšåšæä»¬ç FLE æ ŒåŒäžïŒè¡šç€ºäžº:
{
"type": ".obj",
".text": [
"ð€: main 20 0",
"ð¢: f3 0f 1e fa 55 48 89 e5 bf 29 00 00 00 e8",
"â: .rel(add - 4)", // éŸæ¥åšéèŠå°è¿éæ¿æ¢æ call æä»€çç®æ å°åïŒååèïŒ
"ð¢: 5d c3"
]
}Tip
x86-64 ç call æä»€æ ŒåŒæ¯ïŒ
- äžäžªåèçæäœç ïŒ
0xE8ïŒ - å䞪åèççžå¯¹åç§»éïŒå°ç«¯åºïŒ
对åºç Relocation ç»æäœïŒ
Relocation {
.type = RelocationType::R_X86_64_PC32, // 32äœçžå¯¹å¯»å
.offset = 14, // éå®äœäœçœ®ïŒåšèå
çåç§»ïŒ
.symbol = "add", // ç®æ 笊å·
.addend = -4 // åç§»éè°æŽåŒ
}è¿è®°åŸ FLE æ ŒåŒæä»¶ç纊å®åïŒè¿é .rel(add - 4) 衚瀺äžäžªçžå¯¹éå®äœïŒR_X86_64_PC32 ç±»åïŒïŒå
¶ç®æ ç¬Šå·æ¯ addïŒéå åŒäžº -4ãäžä»»å¡äºäžçç»å¯¹éå®äœäžåïŒè¿éååšçäžæ¯åœæ°çç»å¯¹å°åïŒèæ¯ãèŠè·³å€è¿ããè¿ç§è®Ÿè®¡æäž€äžªéèŠçäŒç¹ïŒ
- 代ç å¯ä»¥å 蜜å°å åçä»»äœäœçœ®ïŒå€©ç¶æ¯æäœçœ®æ å ³ïŒèäžéèŠåšæéŸæ¥åšè¿è¡æ¶ä¿®æ£å°åïŒ
- 跳蜬æä»€æŽçïŒä»£ç äœç§¯åªèŠäžè¶ è¿ 4GBïŒå°±åªéèŠ 32 äœåç§»éïŒ
计ç®å ¬åŒéåžžç®åïŒ
å ¶äžïŒ
- S (Symbol)ïŒç®æ 笊å·çå°åïŒæ¯åŠ
addåœæ°çäœçœ®ïŒ - A (Addend)ïŒéå®äœé¡¹äžçéå åŒïŒè¿å°±æ¯
- 4掟äžçšåºçå°æ¹ïŒïŒ - P (Place)ïŒéå®äœäœçœ®çå°åïŒ
callæä»€æäœæ°çäœçœ®ïŒ
æ¯åŠïŒåŠæïŒ
addåœæ°åš0x4000A0callæä»€çæäœæ°åš0x400035- éå åŒæ¯
-4
é£ä¹ïŒ
æç»çæºåšç å°±æ¯ïŒ
e8 67 00 00 00 ; call add
Note
䞺ä»ä¹éèŠ addendïŒéå åŒïŒïŒè¿äž x86-64 ççšåºè®¡æ°åš %rip çå·¥äœæ¹åŒæå
³ïŒ
X: E8 ; call rel32 çæäœç (1 Byte)
X+1: ?? ?? ?? ?? ; 32 äœåç§»é (4 Bytes)
X+5: ?? ?? ?? ?? ; äžäžæ¡æä»€
-
callæä»€äžçåç§»éæ¯çžå¯¹äºçšåºè®¡æ°åš%ripçïŒèåšåœåæä»€æ§è¡æ¶ïŒ%ripå·²ç»æåäºäžäžæ¡æä»€ïŒä¹å°±æ¯$X+5$ - æä»¥åœ CPU æ§è¡å°è¿äžª
callæä»€æ¶ïŒå®é éèŠè·³èœ¬çè·çŠ»æ¯$\text{åç§»é} = S - (X+5)$ - éŸæ¥æ¶ïŒéå®äœäœçœ®çå°åæ¯
$P = X+1$ ïŒå æ€ïŒåŠæå ¬åŒäžº$\text{åç§»é} = S + A - P = S + A - (X+1)$ ïŒä»èåŸå°$A = -4$ ïŒå³addend䞺-4ã
ç®åæ¥è¯ŽïŒå°±æ¯éå®äœäœçœ®çå°åïŒåäžäžæ¡æä»€çå°å差䞺 -4ã
äœ å°åšäžäžåŠæç è®¡ç®æºç³»ç»å®ç° 1 äžåŠä¹ å°æŽå€å ³äº CPU æµæ°Žçº¿äžæä»€æ§è¡çç¥è¯ã
请åšäœ å®ç°çéŸæ¥åšåºç¡äžïŒè¿äžæ¥æ¯æçžå¯¹éå®äœã
Tip
è°è¯çžå¯¹éå®äœæ¶ïŒæå°æ¯äžæ¥çåºæ¬ä¿¡æ¯å¯èœäŒææåž®å©ïŒ
- ç®æ 笊å·çå°åïŒSïŒ
- éå®äœäœçœ®çå°åïŒPïŒ
- 计ç®åŸå°çåç§»é
- æç»åå ¥çåè
宿åïŒè¿è¡æµè¯æ¥éªè¯ïŒ
make test_3Note
æä»¬åšè¿éè§£éäžäžèäžïŒäžºä»ä¹å
¥å£ç¹æ»æ¯å䞺 _start çåœæ°ã
C äž C++ çŒè¯åšåšéŸæ¥æ¶äŒé»è®€å° libcïŒå³ C è¯èšæ ååºéŸæ¥è¿æ¥ïŒå
¶æåžžè§çå®ç°æ¯ glibcã
è¿äžªåºäŒå®ä¹äžäžª _start åœæ°ïŒäœäžºçšåºçäœçº§å
¥å£ç¹ãè¿äžªåœæ°èŽèޣ仿 äžè§£æåœä»€è¡åæ°ãåå§å C++ å
šå±å¯¹è±¡ãåå§åå å
å管ççïŒå¹¶è¿äžæ¥è°çš main åœæ°ïŒèœ¬ç§»æ§å¶æã
å ¶ä»è¯èšïŒåŠ GoãRust çïŒäºŠæç±»äŒŒçæºå¶ã
ä»ä»»å¡äžåŒå§ïŒæä»¬åŒå§å
å« tests/common/minilibc.hïŒè¿äžªåºæš¡æäº libc çéšååèœïŒæäŸé¢å®ä¹ç _start åœæ°ã
åšåé¢çä»»å¡äžïŒæä»¬å讟æ¯äžªç¬Šå·åªåšäžäžªå°æ¹å®ä¹ãäœåšå®é çŒçšäžïŒç»åžžäŒéå°åå笊å·ã让æä»¬çäžäžªäŸåïŒ
// config.c
int debug_level = 0; // é»è®€é
眮
// main.c
int debug_level = 1; // èªå®ä¹é
çœ®è¿æ¶éŸæ¥åšè¯¥æä¹åïŒåºè¯¥çšåªäžª debug_levelïŒ
é€äºå€çåå笊å·çé®é¢ïŒéŸæ¥åšè¿éèŠæ£ç¡®å€ç笊å·çå¯è§æ§ãåš C è¯èšäžïŒæä»¬å¯ä»¥çš static å
³é®åå°ç¬Šå·å£°æäžºå±éšçïŒ
// foo.c
static int counter = 0; // å±éšç¬Šå·ïŒåªå𿬿件å¯è§
// main.c
extern int counter; // éè¯¯ïŒæŸäžå°ç¬Šå· counterè¿ç§æ
åµåºè¯¥åšéŸæ¥æ¶è¢«åç°å¹¶æ¥éãå äžºå¯¹äº main.c æ¥è¯ŽïŒfoo.c äžçå±éšç¬Šå· counter çžåœäºæªå®ä¹ç¬Šå· ââ 宿 ¹æ¬å°±ãçäžå°ãè¿äžªç¬Šå·ã
䞺äºè§£å³ç¬Šå·å²çªåå¯è§æ§é®é¢ïŒC è¯èšçŒè¯åšå®ä¹äºå šå±ç¬Šå·çã区床ãïŒ
- 区笊å·ïŒStrongïŒïŒæ®éçå šå±ç¬Šå·
- 匱笊å·ïŒWeakïŒïŒå¯ä»¥è¢«èŠççå€é项
æåžžè§ççšæ³æ¯ïŒçšåŒ±ç¬Šå·æ¥æäŸå¯èŠççé»è®€å®ç°ïŒ
// logger.c
__attribute__((weak)) // æ 记䞺匱笊å·
void init_logger() { // é»è®€çåå§ååœæ°
// 䜿çšé»è®€é
眮
}
// main.c
void init_logger() { // 区笊å·äŒèŠçé»è®€å®ç°
// 䜿çšèªå®ä¹é
眮
}åš FLE æ ŒåŒäžïŒåŒ±ç¬Šå·çš ð 衚瀺ïŒ
{
"type": ".obj",
".text": [
"ð: init_logger 20 0", // 匱笊å·
"ð¢: 55 48 89 e5 ..."
]
}éŸæ¥æ¶ïŒç¬Šå·å²çªçå€çè§ååŸç®åïŒ
-
区笊å·å¿ é¡»å¯äžïŒåŠåæ¥é
// a.c int max(int x, int y) { return x > y ? x : y; } // b.c int max(int x, int y) { return x > y ? x : y; } // é误ïŒéå€å®ä¹ïŒ
-
区笊å·äŒå äºåŒ±ç¬Šå·
// lib.c __attribute__((weak)) void init() { /* é»è®€å®ç° */ } // main.c void init() { /* èªå®ä¹å®ç°ïŒäŒèŠçé»è®€çæ¬ */ }
-
å€äžªåŒ±ç¬Šå·æ¶ä»»æéæ©
// a.c __attribute__((weak)) int debug = 0; // b.c __attribute__((weak)) int debug = 1;
Note
åš C++ äžïŒinline åœæ°æåéé垞被çŒè¯åšå®ç°äžº Vague LinkageïŒè¡äžºæç¹ç±»äŒŒäºåŒ±ç¬Šå·ãæš¡æ¿ãå®ä¹åšç±»å
çæååœæ°ãconstexpr å鿝éåŒ inline çïŒä¹äŒä»¥çžåæ¹åŒå®ç°ã
æèäžäžïŒè¿éœæ¯äžºä»ä¹ïŒæ³šæ C++ ç inline 修饰笊çå«ä¹ã
è¯·è®©äœ çéŸæ¥å𿝿è¿äºè§åïŒå¹¶åšè§å被è¿åæ¶èŸåºåççé误信æ¯ïŒ
- 对äºåŒºç¬Šå·å²çªçæ
圢ïŒåºåœèŸåº
"Multiple definition of strong symbol: ${sym.name} - å¯¹äºæŸäžå°ç¬Šå·å®ä¹çæ
圢ïŒåºåœèŸåº
"Undefined symbol: ${sym.name}ã
Tip
æµè¯èæ¬éçšèŸäžºå®œæŸçå¹é
æ¹åŒïŒåªèŠæ£æµå° stderr äžçæäžè¡å
å«ç¬Šåæ ŒåŒçå笊䞲å³è®€äžºæµè¯éè¿ãäœ å¯ä»¥ïŒ
- éè¿
throw std::runtime_error(err_message)æåºåŒåžžïŒå®éªæ¡æ¶äŒèªåšæè·å¹¶èŸåºé误信æ¯å°æ åéè¯¯æµ - çŽæ¥å
stderrèŸåºé误信æ¯ïŒäœ¿çšstd::cerræfprintfïŒïŒç¶åè°çšexit(1)äžæ¢çšåº
Important
åšå®é
代ç äžïŒé€äºæŸåŒå£°æçååå±éšç¬Šå·ä¹å€ïŒäœ è¿äŒéå°äžäºç¹æ®çååå±éšç¬Šå·æ
åµãäŸåŠïŒå¯¹äžåæä»¶äžçå笊䞲åé¢éïŒçŒè¯åšå¯èœçæååçå±éšç¬Šå·ïŒæ¯åŠ .LC0ïŒã
äžåç®æ æä»¶çååå±éšç¬Šå·æ¯è¢«å 讞çïŒå 䞺æ¯äžªå±éšç¬Šå·ä» åšåœåç®æ æä»¶äžå¯è§ã
Tip
䞺äºå€çè¿äºæ
åµïŒäœ éèŠæ³åæ³å°æ¥èªäžåæä»¶çååå±éšç¬Šå·åºååŒæ¥ãäœ å¯ä»¥åšç¬Šå·è§£ææ¶åšå±éšç¬Šå·ååæ·»å ç®æ ååïŒFLEObject::nameïŒäœäžºåçŒïŒå¹¶åšéå®äœæ¶äœ¿çšå
å«åçŒç宿Žç¬Šå·åè¿è¡éå®äœæ¥æŸãè°è¯æ¶ïŒäœ ä¹å¯ä»¥çšå®æŽç笊å·åæ¥å®äœé®é¢ã
宿åïŒäœ çéŸæ¥åšå°±èœæ£ç¡®å€ç笊å·å²çªåå±éšç¬Šå·äºãè¿è¡æµè¯æ¥éªè¯ïŒ
make test_4å°ç®å䞺æ¢ïŒæä»¬å€ççéœæ¯ 32 äœçå°åïŒR_X86_64_32 å R_X86_64_PC32ïŒãäœåš 64 äœç³»ç»äžïŒææ¶æä»¬éèŠå®æŽç 64 äœå°åãæ¯åŠïŒ
// äžäžªå
šå±æ°ç»
int numbers[] = {1, 2, 3, 4};
// äžäžªæåè¿äžªæ°ç»çæé
int *ptr = &numbers[0]; // éèŠå®æŽç 64 äœå°åïŒåšéŸæ¥æ¶ïŒæä»¬éèŠç¥é numbers çå°åïŒå¹¶åå
¥æ°æ®æ®µäœäžº ptr 笊å·çåŒãx86-64 ç³»ç»äžïŒint * ç±»åæ¯ 64 äœçïŒå 䞺å
¶æåçå°åæ¯ 64 äœçã
è¿ç§æ
åµäžïŒçŒè¯åšäŒçæäžäžªæ°çéå®äœç±»åïŒR_X86_64_64ïŒïŒ
{
"type": ".obj",
".data": [
"ð€: numbers 16", // numbers æ°ç»
"ð¢: 01 00 00 00", // 1
"ð¢: 02 00 00 00", // 2
"ð¢: 03 00 00 00", // 3
"ð¢: 04 00 00 00" // 4
],
".data.rel.local": [
"ð€: ptr 8",
"â: .abs64(numbers + 0)" // éèŠ numbers ç宿Žå°å
]
...
}泚æé£äžª .abs64 ââ è¿æ¯äžäžªæ°çéå®äœç±»åïŒR_X86_64_64ïŒïŒå®åè¯éŸæ¥åšïŒåšè¿éå¡«å
¥ç¬Šå·çå®æŽ 64 äœå°åã
对åºç Relocation ç»æäœåŠäžïŒ
Relocation {
.type = RelocationType::R_X86_64_64, // 64äœç»å¯¹å¯»å
.offset = 0, // éå®äœäœçœ®
.symbol = "numbers", // ç®æ 笊å·
.addend = 0 // åç§»é
}äœ ç任塿¯æ¯æè¿ç§éå®äœãå€çè¿ç§éå®äœæ¶ïŒè®¡ç®å ¬åŒäž 32 äœç»å¯¹å¯»å çžåïŒäœåå ¥æ¶éèŠåå ¥å®æŽç 8 åèã
Tip
äœ¿çš 64 äœæŽæ°ååšå°åïŒå°å¿æŽæ°æº¢åºã
宿åïŒäœ çéŸæ¥åšå°±èœå€ç 64 äœå°åäºãè¿è¡æµè¯æ¥éªè¯ïŒ
make test_5å°ç®å䞺æ¢ïŒæä»¬æææçšåºçæææ°æ®éœæŸåšäžäžªæ®µäžãè¿çèµ·æ¥åŸæ¹äŸ¿ïŒäœæ£åŠæä»¬åš Attack Homework äžæåŠå°ç飿 ·ïŒè¿ç»äºæ»å»è 篡æ¹ä»£ç çæºäŒãæ¯åŠïŒ
void hack() {
// 1. ä¿®æ¹ä»£ç
void* code = (void*)hack;
*(char*)code = 0x90; // åŠæä»£ç æ®µå¯åïŒçšåºå¯ä»¥è¢«ç¯¡æ¹ïŒ
// 2. æ§è¡æ°æ®
char shellcode[] = {...}; // äžäºæ¶æä»£ç
((void(*)())shellcode)(); // åŠææ°æ®æ®µå¯æ§è¡ïŒè¿å°±æ¯æŒæŽïŒ
}䞺äºé²æ¢è¿äºæ»å»ïŒç°ä»£ç³»ç»éçšå ååæ®µä¿æ€æºå¶ãåš FLE æ ŒåŒäžïŒæä»¬ççŒè¯åšå·²ç»å°ä»£ç åå䞺äºäžåçèïŒ
{
"type": ".obj",
"shdrs": [
{
"name": ".text",
"type": 1,
"flags": 1,
"addr": 0,
"offset": 0,
"size": 26
},
{
"name": ".data",
"type": 1,
"flags": 1,
"addr": 0,
"offset": 0,
"size": 4
},
{
"name": ".bss",
"type": 8,
"flags": 9,
"addr": 0,
"offset": 0,
"size": 4096
},
{
"name": ".rodata",
"type": 1,
"flags": 1,
"addr": 0,
"offset": 0,
"size": 6
}
],
".text": [
"ð€: main 26 0",
"ð¢: 55 48 89 e5 bf",
"â: .abs(.rodata + 0)",
"ð¢: b8 00 00 00 00 e8",
"â: .rel(printf - 4)",
"ð¢: b8 00 00 00 00 5d c3"
],
".data": [
"ð€: counter 4 0",
"ð¢: 03 00 00 00" // å·²åå§åæ°æ®
],
".bss": [
"ð€: buffer 4096 0" // æªåå§åæ°æ®ïŒå€§å°äžº 4096
],
".rodata": [
"ð·ïž: .rodata 0 0",
"ð¢: 48 65 6c 6c 6f 00" // "Hello"
]
}è倎ïŒsection headersïŒæ¯ç®æ æä»¶äžçéèŠå æ°æ®ïŒå®æè¿°äºæ¯äžªèç屿§åäœçœ®ä¿¡æ¯ãåšæä»¬ç FLE æ ŒåŒäžïŒæ¯äžªè倎å å«ïŒ
nameïŒèçåç§°ïŒåŠ.textã.dataçïŒtypeïŒèçç±»åïŒåŠä»£ç ãæ°æ®çïŒflagsïŒèç屿§æ å¿addrïŒèåšå åäžçèµ·å§å°åoffsetïŒèåšæä»¶äžçåç§»ésizeïŒèç倧å°
è¿äºä¿¡æ¯å¯¹éŸæ¥åšæ¥è¯ŽéåžžéèŠââå®ä»¬æè¿°äºç®æ æä»¶äžå䞪èçç»ç»æ¹åŒãéŸæ¥åšéèŠäœ¿çšè¿äºä¿¡æ¯æ¥å®äœå读åå䞪èçå 容ïŒåå¹¶æ¥èªäžåæä»¶çåç±»åèïŒå¹¶åšçæå¯æ§è¡æä»¶æ¶ç¡®å®æç»çå ååžå±ã
Note
Linux çæ å ELF æ ŒåŒäžååšäž€ç§éèŠçè§åŸ:
- éŸæ¥è§åŸïŒLinking ViewïŒ ç±è倎ïŒSection HeadersïŒè¡šæè¿°ïŒå
å«éŸæ¥æ¶éèŠç诊ç»ä¿¡æ¯ïŒåŠ
.textã.dataã.bssçèãè¿äºä¿¡æ¯äž»èŠçšäºéŸæ¥åè°è¯ïŒåšæç»ç坿§è¡æä»¶äžå¹¶éå¿ éã - è¿è¡è§åŸïŒExecution ViewïŒ ç±çšåºå€ŽïŒProgram HeadersïŒè¡šæè¿°ïŒå®ä¹äºçšåºè¿è¡æ¶çå åæ®µïŒsegmentïŒãå®æè¿°åŠäœå°æä»¶æ å°å°å åïŒæ¯å 蜜çšåºïŒloaderïŒå¿ éçä¿¡æ¯ïŒåšå¯æ§è¡æä»¶äžäžå¯æçŒºã
åšæ åç ELF äžïŒäžäžªå
åæ®µéåžžäŒå
å«å€äžªå
·æçžåæééæ±çèãäŸåŠïŒå¯è¯»åçæ°æ®æ®µéåžžåæ¶å
å« .data å .bss èïŒå®ä»¬äŒè¢«æ å°å°åäžåè¿ç»çå
ååºåäžãè¿ç§è®Ÿè®¡å¯ä»¥åå°å
åç¢çïŒç®åçšåºçå 蜜è¿çšã
䞺äºè®©ååŠä»¬äžæ³šäºçè§£éŸæ¥çåºæ¬æŠå¿µïŒæä»¬ç FLE æ ŒåŒéçšäºç®åç讟计ïŒå§ç»ä¿æèåæ®µçäžå¯¹äžæ å°ïŒå°æ¯äžªèéœåç¬æ å°äžºäžäžªå åæ®µãè¿ç§ç®åèœç¶äžå€äŒåïŒäœæŽå®¹æçè§£åå®ç°ã
è¿äºèéèŠè¢«æ å°å°å åäžïŒå ·äœç±»ååå«ä¹åŠäžïŒ
| è | äœçš | æé |
|---|---|---|
.text è |
åæŸçšåºä»£ç | r-x ïŒè¯»ãæ§è¡ïŒ |
.rodata è |
åæŸåžžéæ°æ® | r--ïŒåªè¯»ïŒ |
.data è |
åæŸå·²åå§åçå šå±åé | rw-ïŒè¯»/åïŒ |
.bss è |
åæŸæªåå§åçå šå±åé | rw-ïŒè¯»/åïŒ |
äœ ç任塿¯æ¯æèçå åæ å°ïŒåšçšåºå€Žäžäžºæ¯äžªè讟眮çžåºçæé级å«ïŒå¹¶ä¿è¯æ¯äžªèçèµ·å§å°å䞺 4KB 对éœãæ€å€ïŒäœ è¿å¯ä»¥åç宿èç顺åºä»¥åå°å åç¢çã
Tip
æä»¬äœ¿çšæäžŸ enum class PHF æ¥å®ä¹çšåºå€Žäžç段æéïŒçšäºè¿å¶åŒïŒåŠ 1, 2, 4ïŒè¡šç€º RïŒå¯è¯»ïŒãWïŒå¯åïŒãXïŒå¯æ§è¡ïŒãè¿äºæ å¿å¯æäœææäœç»åïŒäŸåŠ PHF::R | PHF::X 衚瀺该段æ¢å¯è¯»å坿§è¡ïŒå
¶äž PHF:: 衚瀺äœçšåïŒæ¯å¿
é¡»çã
Tip
åšå®é
çŒè¯çæçç®æ æä»¶äžïŒäœ å¯èœäŒéå°äžäºç¹æ®åœåçèïŒåŠ .text.startupã.rodata.str1.1 çãè¿äºæ¯çŒè¯åšäžºäºäŒåç®çèªåšçæçïŒ
.text.startupïŒåæŸçšåºåå§åçžå ³ä»£ç ïŒåŠmainåœæ°ïŒ.text.unlikely/.text.hotïŒçšäºåºäºæŠçç代ç åžå±äŒå.rodata.str1.1ïŒåæŸå笊䞲垞éïŒæ°å衚瀺对éœèŠæ±
å€çè¿äºèæ¶ïŒäœ å¯ä»¥
- ä¿æç¬ç«ïŒåç §å¯¹åºçæ åè讟眮æé
.text.*讟眮䞺r-xïŒè¯»/æ§è¡ïŒ.rodata.*讟眮䞺r--ïŒåªè¯»ïŒ.data.*讟眮䞺rw-ïŒè¯»/åïŒ.bss.*讟眮䞺rw-ïŒè¯»/åïŒ
- å°å®ä»¬åå¹¶å°å¯¹åºçæ åèäžïŒçžå¯¹å€æïŒ
.text.*åå¹¶å°.text.rodata.*åå¹¶å°.rodata.data.*åå¹¶å°.data.bss.*åå¹¶å°.bss
åå¹¶è¿äºèå¯ä»¥åå°å åç¢çïŒç®åçšåºçå ååžå±ïŒè¿ä¹æ¯æ åéŸæ¥åšçåžžè§åæ³ã
Important
.bss èçžå¯¹ç¹æ®ãç±äºå®äžéšçšäºåæŸé¶åå§åçå
šå±åéïŒå
šå±åéçé»è®€åå§åå³äžºé¶åå§åïŒïŒäžºèç空éŽïŒç®æ æä»¶åªåšè倎ïŒshdrsïŒè®°åœäºè¿ç空éŽç倧å°ïŒèäžäŒå®é
ååšäžå 0ã
åšå¯æ§è¡æä»¶äžïŒåºäºçžååå ïŒ.bss 段çäžå 0 äŸç¶äžåºè¯¥è¢«å®é
ååšã
å 蜜åšäŒèªåšå° .bss 段æ å°äžºäžååå§å䞺 0 ç对åºçå
ååºåã
Tip
åš .bss èå®ä¹ç笊å·ïŒå
¶ size 屿§å°€å
¶éèŠââå äžºè¿æ¯è·åçžå
³å
ååžå±çå¯äžåæ³ã
宿åïŒäœ çéŸæ¥åšå°±èœçæå ·ææ£ç¡®å ååžå±åè®¿é®æéç坿§è¡æä»¶äºãè¿è¡æµè¯æ¥éªè¯ïŒ
make test_6æåäœ å®æäºææåºç¡ä»»å¡ïŒç°åšè®©æä»¬éªè¯æŽäžªéŸæ¥åšçåèœã
make testäœ åºè¯¥çå°ïŒ
Preparing FLE Tools...
â FLE Tools compiled successfully
Preparing minilibc...
â minilibc compiled successfully
Running 12 test cases...
â nm Tool Test [2/2]: Passed
â Single File Test [3/3]: Passed
â Absolute Addressing Test [3/3]: Passed
â Absolute + Relative Addressing Test [4/4]: Passed
â Position Independent Executable Test [5/5]: Passed
â Strong Symbol Conflict Test [3/3]: Passed
â Weak Symbol Override Test [4/4]: Passed
â Multiple Weak Symbol Warning [5/5]: Passed
â Local Symbol Access Test [7/7]: Passed
â 64-bit Absolute Relocation Test [3/3]: Passed
â BSS Section Linking Test [5/5]: Passed
â Section Permission Control Test [10/10]: Passed
âââââââââââââââââââââââââââââââââââââââ³âââââââââ³ââââââââ³ââââââââââââ³ââââââââââââââââââââââ
â Test Case â Result â Time â Score â Message â
â¡âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ©
â nm Tool Test â PASS â 0.36s â 10.0/10.0 â All steps completed â
â Single File Test â PASS â 0.27s â 10.0/10.0 â All steps completed â
â Absolute Addressing Test â PASS â 0.29s â 10.0/10.0 â All steps completed â
â Absolute + Relative Addressing Test â PASS â 0.60s â 10.0/10.0 â All steps completed â
â Position Independent Executable â PASS â 0.93s â 10.0/10.0 â All steps completed â
â Test â â â â â
â Strong Symbol Conflict Test â PASS â 0.70s â 10.0/10.0 â All steps completed â
â Weak Symbol Override Test â PASS â 0.78s â 10.0/10.0 â All steps completed â
â Multiple Weak Symbol Warning â PASS â 0.85s â 10.0/10.0 â All steps completed â
â Local Symbol Access Test â PASS â 0.46s â 10.0/10.0 â All steps completed â
â 64-bit Absolute Relocation Test â PASS â 0.37s â 10.0/10.0 â All steps completed â
â BSS Section Linking Test â PASS â 0.77s â 10.0/10.0 â All steps completed â
â Section Permission Control Test â PASS â 1.27s â 10.0/10.0 â All steps completed â
âââââââââââââââââââââââââââââââââââââââŽâââââââââŽââââââââŽââââââââââââŽââââââââââââââââââââââ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ®
â Total Score: 120.0/120.0 (100.0%) â
â°âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¯
请åèæ¥åæš¡æ¿éçšæåïŒåºäºå®éªæ¥åæš¡æ¿ïŒå®æå®éªæ¥åã
äœ¿çš GitHub Classroom è¿è¡æäº€ãè¯·äœ ç¡®ä¿ææä»£ç å·²æäº€å°äœ ç对åºä»åºïŒGitHub Actions äŒèªåšè¿è¡æµè¯ïŒå ¶èŸåºäœäžºæä»¬çè¯åäŸæ®ã
åæ°ç±æ£ç¡®æ§è¯åå莚éè¯å䞀éšåç»æïŒæ£ç¡®æ§è¯åå 60%ïŒèŽšéè¯åå 40%ïŒå³ïŒ
å ¶äžïŒæ£ç¡®æ§è¯åç± GitHub Classroom èªåšè®¡ç®ïŒèŽšéè¯åç±å©ææ ¹æ®ä»£ç 飿 Œåå®éªæ¥å绌åè¯äŒ°ïŒå ·äœè¡¡éå çŽ äžºïŒ
- 代ç 飿 Œ
- 代ç 衚蟟èœå区ïŒé»èŸæž æ°ïŒä»£ç ç®æŽïŒä» åšå¿ èŠæ¶æ·»å 泚é
- é²åŸ¡æ§çŒçšïŒè¿è¡å€å±æ¬¡çéè¯¯æ£æ¥
- åŠæäœ äœ¿çš C++ 飿 Œè¿è¡çŒç ïŒè¯·ç§¯æäœ¿çš C++ æ ååºïŒèééå€é 蜮å
- å®éªæ¥å
- å®éªæ¥åå 容宿Žãæ ŒåŒè§èãç»ææž æ°
- å®éªæ¥åå 容äžä»£ç äžèŽïŒæ ææŸççŸïŒäœç°åºå¯¹å®éªèå¯ç¥è¯çåºæ¬äºè§£
- ææèïŒææ»ç»ïŒæåæïŒæåæ°
- 对å®éªæäŸæä»·åŒçåéŠå建议ïŒç§¯æåäžåŒæºåäœ
äœ å¯ä»¥é 读è°è¯æåïŒäºè§£åŠäœäœ¿çšè¯æµèæ¬å VSCode è°è¯ã
Tip
åé¢çåºå以å忥æ¢çŽ¢å§ïŒ
åšå®æåºç¡ä»»å¡çæ çšä¹åïŒæŽå¹¿éç倩尿£çåŸ æä»¬å»æ¢çŽ¢ãç°ä»£éŸæ¥åšæ©å·²è¶ è¶äºç®åç代ç ç»åïŒå®éèŠåšæ§èœãå Œå®¹æ§ãå®å šæ§çå€äžªç»ŽåºŠäžè¿è¡åèïŒtrade-offïŒïŒä»¥æ»¡è¶³å€æèœ¯ä»¶ç³»ç»çéæ±ã
ä»¥äžæ¯äžäºåŒåŸæ¢çŽ¢çæ¹åïŒåŠæäœåçååŠå¯ä»¥å°è¯å®ç°ïŒ
-
éæåºæ¯æïŒéè¿è®Ÿè®¡äžç§åœæ¡£æ ŒåŒïŒ
.aæä»¶ïŒæ¥æå å€äžªç®æ æä»¶ïŒäœ çéŸæ¥åšå¯ä»¥å®ç°æééŸæ¥ââåªæåçšåºå®é 䜿çšçç¬Šå·æåšçç®æ æä»¶ãè¿äžä» èçäºç£ç空éŽïŒæŽéèŠçæ¯é¿å äºäžå¿ èŠçä»£ç æ®µè¢«å 蜜å°å åã -
åšæéŸæ¥æ¯æïŒå®å 讞å€äžªè¿çšå ±äº«åäžä»œä»£ç ïŒæŸèéäœå åå çšãèŠæ¯æåšæéŸæ¥ïŒäœ éèŠçæäœçœ®æ å ³å¯æ§è¡æä»¶ïŒPIEïŒïŒå®ç°å šå±å移衚ïŒGOTïŒå€çæ°æ®åŒçšïŒä»¥åéè¿è¿çšéŸæ¥è¡šïŒPLTïŒå®ç°å»¶è¿ç¬Šå·ç»å®ãæ€å€ïŒåšæéŸæ¥åšè¿éèŠå€ç倿ç笊å·è§£æè§ååå 蜜æ¶éå®äœã
-
笊å·çæ¬ç®¡çïŒå¯¹äºç»Žæ€é¿ææ¯æçå ±äº«åºè³å ³éèŠãéè¿çæ¬èæ¬ïŒäœ å¯ä»¥äžºæ¯äžªå¯Œåºç¬Šå·æå®çæ¬ä¿¡æ¯ïŒå®ç°å€çæ¬å ±åãè¿äœ¿åŸåºå¯ä»¥åšå¢å æ°åèœçåæ¶ä¿æå¯¹æ§çæ¬ ABI çå Œå®¹ïŒé¿å ãå ±äº«åºäŸèµå°ç±ããäœ éèŠè®Ÿè®¡çæ¬å®ä¹çè¯æ³ïŒå¹¶åšç¬Šå·è§£ææ¶æ£ç¡®å€ççæ¬ä¿¡æ¯ã
-
å¢ééŸæ¥ïŒççŒäºæååŒåæçãéè¿åªéæ°éŸæ¥åçååçéšåïŒå¯ä»¥å€§å¹ 猩çæå»ºæ¶éŽãè¿éèŠäœ 讟计äžäžªäŸèµåŸæ¥è¿œèžªæä»¶éŽçå ³ç³»ïŒå¹¶èœå€åç¡®å€æç¬Šå·çº§å«çååãäœ è¿éèŠèèåŠäœå€çè°è¯ä¿¡æ¯çå¢éæŽæ°ã
-
è°è¯æ¯æïŒå·¥çšå®è·µäžäžå¯æçŒºçåèœãé€äºä¿çåºæ¬ç笊å·è¡šïŒå®æŽçè°è¯æ¯æè¿éèŠå€ç DWARF æ ŒåŒçè°è¯ä¿¡æ¯ïŒå æ¬è¡å·è¡šãåéæè¿°ãç±»åä¿¡æ¯çãè¿äºä¿¡æ¯éèŠåšéŸæ¥è¿çšäžè¢«æ£ç¡®éå®äœååå¹¶ãæ€å€ïŒäžºäºè®©åŒåè èœå€äœ¿çš GDB çæ åè°è¯å·¥å ·ïŒäœ è¿éèŠçŒå GDB èæ¬æ¥æ¯æ FLE æ ŒåŒæä»¶çè§£æïŒäœ¿è°è¯åšèœå€æ£ç¡®æŸç€ºæºç äœçœ®ãåéåŒåè°çšæ çä¿¡æ¯ã
-
å®å šå¢åŒºïŒéè¿æ¯æå°å空éŽéæºåïŒASLRïŒåçæäœçœ®æ å ³å¯æ§è¡æä»¶ïŒPIEïŒïŒå¯ä»¥ææé²èçŒå²åºæº¢åºåä»£ç æ³šå ¥æ»å»ãæ€å€ïŒäœ è¿å¯ä»¥æ¯æ RELROïŒRELocation Read-OnlyïŒæºå¶ïŒå° GOT 衚讟䞺åªè¯»æ¥é²æ¢ GOT 衚èŠåæ»å»ã
è¿äºæ¢çŽ¢äžäŒè¢«è®¡å ¥è¯åïŒäœå®ä»¬æ¿èœœçæŽæ·±è¿çæä¹ãåŠæäœ æ¿æïŒå¯ä»¥éè¿ Pull Request åäº«äœ çå®ç°å对å®éªæ¡æ¶çæ¹è¿ãäœ ç莡ç®å°åŠæ¶æŒªè¬è¡åŒïŒè®©æŽå€è¿œå¯»ææ¯ä¹çŸçååŠä»äžåçã
æ¬å®éªç± 22 级åŸçµççæç¥éååŠååœæåååŠå ±åæåºå¹¶è®Ÿè®¡å®æãåšå®éªè®Ÿè®¡è¿çšäžïŒ21 级åŸçµççæœä¿èŸŸååŠäžºå®éªææ¡£ççŒåæäŸäºè¯žå€å»ºè®Ÿæ§ç建议ïŒåšæ€è¡šç€ºè¡·å¿çæè°¢ã
ç¹å«æè°¢æŽäºé¹ææåçæ¶ææå¯¹æ¬å®éªçæå¿æå¯Œäžå€§åæ¯æãä»ä»¬çäžäžè§è§£åå®èŽµå»ºè®®å¯¹å®éªçå®åèµ·å°äºéèŠçæšåšäœçšã