বাইনারি ফাইলকে সি / সি ++ স্ট্রিং আক্ষরিক হিসাবে কীভাবে ডাম্প করবেন?


39

আমার একটি বাইনারি ফাইল রয়েছে যা আমি আমার সি উত্স কোডে অন্তর্ভুক্ত করতে চাই (অস্থায়ীভাবে, পরীক্ষার উদ্দেশ্যে) তাই আমি ফাইলের বিষয়বস্তুগুলিকে সি স্ট্রিং হিসাবে প্রাপ্ত করতে চাই, এরকম কিছু:

\x01\x02\x03\x04

সম্ভবত এটি odকি hexdumpইউটিলিটিগুলি ব্যবহার করে ? প্রয়োজনীয় না হওয়ার পরে, যদি স্ট্রিংটি প্রতি 16 টি ইনপুট বাইট পরবর্তী লাইনে আবদ্ধ করতে পারে এবং প্রতিটি লাইনের শুরু এবং শেষে ডাবল-কোটস অন্তর্ভুক্ত করতে পারে তবে এটি আরও সুন্দর হবে!

আমি সচেতন যে স্ট্রিংটিতে নালগুলি এম্বেড করা হবে ( \x00) সুতরাং এই বাইটগুলি স্ট্রিংটি শীঘ্রই বন্ধ হতে বাধা দেওয়ার জন্য কোডে স্ট্রিংয়ের দৈর্ঘ্য নির্দিষ্ট করতে হবে।



আমি অনুরূপ চাই তবে ASCII মুদ্রণযোগ্য গ্লাইফ ধরে রাখি, কেবল 1-127, উদ্ধৃতি, ব্যাকস্ল্যাশ, নাল ইত্যাদিতে অব্যাহতি রেখে
友情 留 留 在 无 盐 11:46

উত্তর:


10

আপনি যা চান তা আপনি প্রায় করতে পারেন hexdump, তবে বিন্যাসের স্ট্রিংয়ে কীভাবে উদ্ধৃতি এবং একক ব্যাকস্ল্যাশগুলি পাবেন তা আমি বুঝতে পারি না। তাই আমি একটি সামান্য পোস্ট প্রসেসিং সঙ্গে sed। বোনাস হিসাবে, আমি প্রতিটি লাইন 4 স্পেসে লিখেও লিখেছি। :)

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/.*/    "&"/'

সম্পাদন করা

চেঞ্জিজ যেমন উল্লেখ করতে পারে, উপরের কমান্ড লাইনটি সংক্ষিপ্ত ডাটা লাইনগুলির সাথে ভালভাবে মোকাবেলা করে না। সুতরাং এখানে একটি নতুন উন্নত সংস্করণ:

hexdump -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'

মালভাইনাস মন্তব্যগুলিতে যেমন উল্লেখ করেছেন , একই বাইটের দীর্ঘ রান সংক্ষেপণ থেকে এটি রোধ -vকরার hexdumpজন্য আমাদের ভার্বোস বিকল্পটিও পাস করতে হবে *

hexdump -v -e '16/1 "_x%02X" "\n"' filename | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/'

যদি ইনপুটটি 16 বাইটের চেয়ে কম হয় তবে এটি অনর্থক এবং অবৈধ উপাদান উত্পাদন করে।
কেনজিজ

@ সেনজিজকান:: ওফস:! এটা কি ভালো?
পিএম 2 রিং

1
যুক্ত করতে হবে -vবিকল্প hexdump, অন্যথায় দীর্ঘ একই ইনপুট বাইট কারণ আউটপুট লাইন বলে এর রান "*"
মার্ভিনিয়াস

@ মালভাইনাস গুড পয়েন্ট! আমি আমার উত্তর সংশোধন করেছি। মাথা আপ জন্য ধন্যবাদ (এবং আমার উত্তর গ্রহণ করার জন্য ধন্যবাদ)।
দুপুর ২ টা

66

xxdএই জন্য একটি মোড আছে। -i/ --includeবিকল্প হবে:

সি আউটপুট ফাইল শৈলী অন্তর্ভুক্ত। Xxd স্টিডিন থেকে না পড়লে একটি সম্পূর্ণ স্ট্যাটিক অ্যারে সংজ্ঞা লেখা হয় (ইনপুট ফাইলের নামানুসারে) is

আপনি এটি #includeডি- তে ফাইলের মধ্যে ফেলে দিতে পারেন এবং তারপরে fooঅন্য কোনও অক্ষরের অ্যারের মতোই অ্যাক্সেস করতে পারেন (বা এটিতে লিঙ্ক করুন)। এটি অ্যারের দৈর্ঘ্যের একটি ঘোষণাও অন্তর্ভুক্ত করে।

আউটপুটটি 80 বাইটে আবৃত হয় এবং মূলত আপনি নিজের হাতে কী লিখতে পারেন তার মতো লাগে:

$ xxd --include foo
unsigned char foo[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
  0x21, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x76, 0x65,
  0x72, 0x79, 0x20, 0x63, 0x75, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x21, 0x20,
  0x57, 0x65, 0x6c, 0x6c, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x0a
};
unsigned int foo_len = 47;

xxdকিছুটা অদ্ভুতভাবে vimবিতরণের অংশ , সুতরাং আপনার সম্ভবত এটি ইতিমধ্যে রয়েছে। যদি তা না হয় তবে এটি আপনি যেখানে পেয়েছেন - আপনি vimউত্সটি থেকে নিজেরাই সরঞ্জামটি তৈরি করতে পারেন ।


নিস! আমি জানতাম না আমি এক্সএক্সডি করেছি। এখন আমাকে কেবল মনে রাখতে হবে এটি পরবর্তী সময় যখন প্রয়োজন হবে তখন এটি উপস্থিত রয়েছে ... বা আমি সম্ভবত পাইথনের প্রয়োজনীয় কার্যকারিতাটি প্রতিলিপি করব। :)
প্রধানমন্ত্রী 2 রিং


@ লাইটনেসেসিনঅরবিট ওপিকে objcopyবাইনারি ডেটা এক্সিকিউটেবলের সাথে একটি অবজেক্ট ফাইল হিসাবে লিঙ্ক করার অনুমতি দেবে, যা দরকারী তবে এখানে যা বলা হচ্ছে ঠিক তা নয়।
নাউটা

1
@ ওয়ান্ডার নওতা: আপনি যেভাবে এখানে foo/ foo_lenএখানে প্রবেশ করতে চান ঠিক তেমনভাবে আপনি এটি অ্যাক্সেস করতে পারবেন এবং আপনি স্টোরেজ স্পেসটি ব্যাপকভাবে নষ্ট করবেন না। আমি দৃ am়বিশ্বাস নিয়েছি যে ওপি আরও ভাল হবে objcopyএবং এটি তার প্রয়োজনীয়তার সাথে মানিয়ে যাবে ।
মনিকার সাথে লাইটনেস রেস

2
objcopyচারপাশে থাকলে ঠিক আছে, তবে এটি পোর্টেবল নয় এবং আউটপুট এমনকি কম। এটি অবশ্যই একটি ভাল স্থায়ী সমাধানের অংশ হতে পারে, তবে এখানে প্রশ্নটি নয়।
মাইকেল হোমার 18

3

xxd ভাল তবে ফলাফলটি অত্যন্ত ভার্জোজ এবং প্রচুর সঞ্চয় স্থান গ্রহণ করে।

আপনি ব্যবহার করে ব্যবহারিকভাবে একই জিনিস অর্জন করতে পারেন objcopy; যেমন

objcopy --input binary \
    --output elf32-i386 \
    --binary-architecture i386 foo foo.o

তারপরে foo.oআপনার প্রোগ্রামের সাথে লিঙ্ক করুন এবং কেবল নীচের চিহ্নগুলি ব্যবহার করুন:

00000550 D _binary_foo_end
00000550 A _binary_foo_size 
00000000 D _binary_foo_start

এটি কোনও স্ট্রিং আক্ষরিক নয়, তবে এটি মূলত একই জিনিস যা সংকলনের সময় একটি স্ট্রিং আক্ষরিক রূপান্তরিত হয় (বিবেচনা করুন যে স্ট্রিং লিটারেলগুলি আসলে রান-টাইমে অস্তিত্বের সাথে থাকে না; প্রকৃতপক্ষে, অন্য উত্তরগুলির কোনও উত্তরই আপনাকে স্ট্রিং আক্ষরিক দেয় না এমনকি সংকলন সময়ে) এবং মূলত একইভাবে অ্যাক্সেস করা যেতে পারে:

unsigned char* ptr = _binary_foo_start;
int i;
for (i = 0; i < _binary_foo_size; i++, ptr++)
   putc(*ptr);

খারাপ দিকটি হ'ল অবজেক্ট ফাইলটি সামঞ্জস্যপূর্ণ করতে আপনার টার্গেট আর্কিটেকচার নির্দিষ্ট করা দরকার এবং এটি আপনার বিল্ড সিস্টেমে তুচ্ছ হতে পারে না।


2

আপনি যা চেয়েছিলেন ঠিক তা হওয়া উচিত:

hexdump -v -e '"\\" "x" 1/1 "%02X"' file.bin ; echo

0

এটি একটি সংক্ষিপ্ত ইউটিলিটি যা আমি লিখেছিলাম যে মূলত একই জিনিসটি হয় (মূলত স্ট্যাক ওভারফ্লোতে পোস্ট করা ):

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

#define MAX_LENGTH 80

int main(void)
{
    FILE *fout = fopen("out.txt", "w");

    if(ferror(fout))
    {
        fprintf(stderr, "Error opening output file");
        return 1;
    }
    char init_line[]  = {"char hex_array[] = { "};
    const int offset_length = strlen(init_line);

    char offset_spc[offset_length];

    unsigned char buff[1024];
    char curr_out[64];

    int count, i;
    int line_length = 0;

    memset((void*)offset_spc, (char)32, sizeof(char) * offset_length - 1);
    offset_spc[offset_length - 1] = '\0';

    fprintf(fout, "%s", init_line);

    while(!feof(stdin))
    {
        count = fread(buff, sizeof(char), sizeof(buff) / sizeof(char), stdin);

        for(i = 0; i < count; i++)
        {
            line_length += sprintf(curr_out, "%#x, ", buff[i]);

            fprintf(fout, "%s", curr_out);
            if(line_length >= MAX_LENGTH - offset_length)
            {
                fprintf(fout, "\n%s", offset_spc);
                line_length = 0;
            }
        }
    }
    fseek(fout, -2, SEEK_CUR);
    fprintf(fout, " };");

    fclose(fout);

    return EXIT_SUCCESS;
}

1
আপনার উত্তরটি আরও কার্যকর হবে যদি আপনি এর সাথে ইনপুট এবং আউটপুট উদাহরণগুলি সরবরাহ করে থাকেন।
not2qubit

0

আপনি যদি অজগর হয়ে থাকেন তবে এটিকে ভেরিয়েবল "বাফ" এ লোড করুন এবং এর মতো কিছু ব্যবহার করুন:

buff2 = buff.encode("hex")
print ("0x"+", 0x".join([buff2[i:i+2] for i in range(0,len(buff2),2)]))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.