2017-02-14 14 views
6

मेरे पास एक NASM असेंबली फ़ाइल है जिसे मैं संयोजन और लिंक कर रहा हूं (इंटेल -64 लिनक्स पर)।मैं ईएलएफ फ़ाइल में किसी अनुभाग के रूप में टेक्स्ट फ़ाइल की सामग्री कैसे जोड़ूं?

एक टेक्स्ट फ़ाइल है, और मैं टेक्स्ट फ़ाइल की सामग्री परिणामी बाइनरी (मूल रूप से एक स्ट्रिंग के रूप में) में दिखाना चाहता हूं। बाइनरी एक ईएलएफ निष्पादन योग्य है।

मेरी योजना ईएलएफ फ़ाइल में एक नया पाठक डेटा अनुभाग बनाना है (पारंपरिक .rodata अनुभाग के समतुल्य)।

आदर्श रूप से, फ़ाइल एल्फ़ फ़ाइल में एक नए सेक्शन के रूप में फ़ाइल वर्बैटिम जोड़ने के लिए एक उपकरण होगा, या फ़ाइल वर्बैटिम को शामिल करने के लिए एक लिंकर विकल्प होगा।

क्या यह संभव है?

उत्तर

14

यह संभव है और OBJCOPY का उपयोग करके BINUTILS में पाया जा सकता है। आप डेटा फ़ाइल को बाइनरी इनपुट के रूप में प्रभावी ढंग से लेते हैं और उसके बाद इसे किसी ऑब्जेक्ट फ़ाइल प्रारूप में आउटपुट करते हैं जिसे आपके प्रोग्राम से जोड़ा जा सकता है।

ओबीजेसीओपी भी एक प्रारंभ और अंत प्रतीक के साथ-साथ डेटा क्षेत्र के आकार का उत्पादन भी करेगा ताकि आप उन्हें अपने कोड में संदर्भित कर सकें। मूल विचार यह है कि आप इसे बताना चाहते हैं कि आपकी इनपुट फ़ाइल बाइनरी है (भले ही यह टेक्स्ट हो); कि आप x86-64 ऑब्जेक्ट फ़ाइल को लक्षित करेंगे; इनपुट फ़ाइल नाम और आउटपुट फ़ाइल नाम निर्दिष्ट करें।

मान लें हम एक इनपुट सामग्री के साथ myfile.txt बुलाया फ़ाइल है: यदि आप 32-बिट वस्तुओं आप कर सकते थे उत्पन्न करना चाहता है तो

objcopy --input binary \ 
    --output elf64-x86-64 \ 
    --binary-architecture i386:x86-64 \ 
    myfile.txt myfile.o 

:

the 
quick 
brown 
fox 
jumps 
over 
the 
lazy 
dog 

कुछ इस तरह एक प्रारंभिक बिंदु होगा उपयोग करें:

objcopy --input binary \ 
    --output elf32-i386 \ 
    --binary-architecture i386 \ 
    myfile.txt myfile.o 

आउटपुटनामक एक ऑब्जेक्ट फ़ाइल होगी। हम objdump और objdump -x myfile.o की तरह एक आदेश का उपयोग कर वस्तु फ़ाइल के शीर्ष लेख की समीक्षा करने के थे, तो हम कुछ इस तरह देखना होगा:

myfile.o:  file format elf64-x86-64 
myfile.o 
architecture: i386:x86-64, flags 0x00000010: 
HAS_SYMS 
start address 0x0000000000000000 

Sections: 
Idx Name   Size  VMA    LMA    File off Algn 
    0 .data   0000002c 0000000000000000 0000000000000000 00000040 2**0 
        CONTENTS, ALLOC, LOAD, DATA 
SYMBOL TABLE: 
0000000000000000 l d .data 0000000000000000 .data 
0000000000000000 g  .data 0000000000000000 _binary_myfile_txt_start 
000000000000002c g  .data 0000000000000000 _binary_myfile_txt_end 
000000000000002c g  *ABS* 0000000000000000 _binary_myfile_txt_size 

डिफ़ॉल्ट रूप से यह फ़ाइल की सामग्री के साथ एक .data खंड बनाता है और यह एक बनाता है प्रतीकों की संख्या जिसका उपयोग डेटा के संदर्भ में किया जा सकता है।

_binary_myfile_txt_start 
_binary_myfile_txt_end 
_binary_myfile_txt_size 

यह प्रभावी रूप से शुरू बाइट, अंत बाइट, और कहा कि वस्तु में फ़ाइल myfile.txt से रखा गया था डेटा के आकार का पता है। OBJCOPY इनपुट फ़ाइल नाम पर प्रतीकों का आधार होगा। myfile.txtmyfile_txt में उलझा हुआ है और प्रतीकों को बनाने के लिए उपयोग किया जाता है।

Idx Name   Size  VMA    LMA    File off Algn 
    0 .data   0000002c 0000000000000000 0000000000000000 00000040 2**0 
        CONTENTS, ALLOC, LOAD, DATA 

आप विशेष रूप से एक .rodata अनुभाग अनुरोध कर रहे हैं कि यह भी READONLY फ्लैग निर्दिष्ट किया होगा:

एक समस्या यह है कि एक .data अनुभाग बनाई गई है जो के रूप में यहाँ देखा पढ़ा है/लिखने/डेटा है।आप विकल्प .data को .rodata में बदलने और आवश्यक ध्वज निर्दिष्ट करने के लिए उपयोग कर सकते हैं।

--rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA 
बेशक

अगर आप अनुभाग आप लाइन में .rodata बदल सकते हैं, केवल पढ़ने के अनुभाग के रूप में ही झंडे के साथ .rodata के अलावा कुछ कॉल करना चाहते हैं नाम आप के लिए ऊपर: आप कमांड लाइन के लिए इस जोड़ सकता है खंड के लिए उपयोग करना चाहते हैं।

उस वस्तु इच्छित प्रकार उत्पन्न करनी चाहिए आदेश के अंतिम संस्करण है:

objcopy --input binary \ 
    --output elf64-x86-64 \ 
    --binary-architecture i386:x86-64 \ 
    --rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA \ 
    myfile.txt myfile.o 

अब आप एक वस्तु फ़ाइल है, तुम कैसे सी कोड में इसके उपयोग कर सकते हैं (एक उदाहरण के रूप)। उत्पन्न प्रतीकों थोड़ा असामान्य हैं और वहाँ OS Dev Wiki पर एक उचित व्याख्या है:

एक आम समस्या है जब एक लिंकर लिपि में परिभाषित मान का उपयोग करने की कोशिश कर कचरा डेटा हो रही है। यह आमतौर पर इसलिए होता है क्योंकि वे प्रतीक को संदर्भित कर रहे हैं। एक लिंकर स्क्रिप्ट में परिभाषित एक प्रतीक (उदा। _ebss =।;) केवल एक प्रतीक है, एक चर नहीं। यदि आप बाहरी uint32_t _ebss का उपयोग कर प्रतीक तक पहुंचते हैं; और फिर _ebss का उपयोग करने का प्रयास करें, कोड _ebs द्वारा संकेतित पते से 32-बिट पूर्णांक को पढ़ने का प्रयास करेगा।

इसका समाधान & _ebs के रूप में या इसे एक अनसुलझा सरणी (बाहरी char _ebss]] के रूप में परिभाषित करके और एक पूर्णांक को कास्टिंग करके _ebs का पता लेना है। साथ

#include <stdint.h> 
#include <stdlib.h> 
#include <stdio.h> 

/* These are external references to the symbols created by OBJCOPY */ 
extern char _binary_myfile_txt_start[]; 
extern char _binary_myfile_txt_end[]; 
extern char _binary_myfile_txt_size[]; 

int main() 
{ 
    char *data_start  = _binary_myfile_txt_start; 
    char *data_end  = _binary_myfile_txt_end; 
    size_t data_size = (size_t)_binary_myfile_txt_size; 

    /* Print out the pointers and size */ 
    printf ("data_start %p\n", data_start); 
    printf ("data_end %p\n", data_end); 
    printf ("data_size %zu\n", data_size); 

    /* Print out each byte until we reach the end */ 
    while (data_start < data_end) 
     printf ("%c", *data_start++); 

    return 0; 
} 

आप संकलन कर सकते हैं और लिंक:

इसे ध्यान में रखते हुए हम इस सी फ़ाइल main.c कहा जाता है बना सकते हैं (सरणी संकेतन _ebss के रूप में स्पष्ट रूप से सरणियों dereferenced किया जाना चाहिए से आकस्मिक पढ़ता रोकता है) :

gcc -O3 main.c myfile.o 
कुछ

उत्पादन दिखना चाहिए:

012,
data_start 0x4006a2 
data_end 0x4006ce 
data_size 44 
the 
quick 
brown 
fox 
jumps 
over 
the 
lazy 
dog 

उपयोग का एक एनएएसएम उदाहरण सी कोड के स्वरूप के समान है।

bits 64 
global _start 

extern _binary_myfile_txt_start 
extern _binary_myfile_txt_end 
extern _binary_myfile_txt_size 

section .text 

_start: 
    mov eax, 1      ; SYS_Write system call 
    mov edi, eax      ; Standard output FD = 1 
    mov rsi, _binary_myfile_txt_start ; Address to start of string 
    mov rdx, _binary_myfile_txt_size ; Length of string 
    syscall 

    xor edi, edi      ; Return value = 0 
    mov eax, 60      ; SYS_Exit system call 
    syscall 

यह इकट्ठा किया और के साथ जोड़ा जा सकता है:: निम्नलिखित विधानसभा nmain.asm बुलाया कार्यक्रम मानक आउटपुट में एक ही स्ट्रिंग Linux x86-64 System Calls का उपयोग कर लिखते हैं

nasm -f elf64 -o nmain.o nmain.asm 
gcc -m64 -nostdlib nmain.o myfile.o 

उत्पादन दिखाई देनी चाहिए के रूप में:

the 
quick 
brown 
fox 
jumps 
over 
the 
lazy 
dog 
+1

उस बरसात के दिन के लिए स्टोर करने के लिए बहुत शैक्षिक और एक "मणि"! –

संबंधित मुद्दे