यह संभव है और 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.txt
myfile_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
उस बरसात के दिन के लिए स्टोर करने के लिए बहुत शैक्षिक और एक "मणि"! –