কীভাবে একক ফাংশনকে অ্যাজডাম্প ব্যবহার করে বিচ্ছিন্ন করা যায়?


91

আমি আমার সিস্টেমে একটি বাইনারি ইনস্টল করেছি এবং একটি প্রদত্ত ফাংশনটির অপ্রয়োজনীয় দিকে নজর দিতে চাই। সাধারণত ব্যবহার করা objdump, তবে অন্যান্য সমাধানগুলিও গ্রহণযোগ্য হবে acceptable

এই প্রশ্নগুলি থেকে আমি শিখেছি যে আমি যদি কেবল সীমানা ঠিকানাগুলি জানি তবে আমি কোডের কিছু অংশ বিযুক্ত করতে সক্ষম হব। এই উত্তর থেকে আমি শিখেছি কীভাবে আমার বিভক্ত ডিবাগ প্রতীকগুলিকে একটি একক ফাইলে পরিণত করা যায়।

এমনকি সেই একক ফাইলে অপারেটিং করে এমনকি সমস্ত কোড বিচ্ছিন্ন করে (অর্থাত্ প্রারম্ভিক বা স্টপ ঠিকানা ছাড়াই, তবে এতে সরল -dপ্যারামিটার objdump), এখনও আমি এই চিহ্নটি কোথাও দেখতে পাচ্ছি না। যা প্রশ্নাবলীর কার্যটি স্থির তাই অনর্থক বোঝায় তাই এটি রফতানি হয় না। তবুও, valgrindফাংশন নামটি রিপোর্ট করবে, তাই এটি কোথাও সংরক্ষণ করতে হবে।

ডিবাগ বিভাগগুলির বিশদটি সন্ধান করে, আমি .debug_strবিভাগটিতে উল্লিখিত নামটি দেখতে পেয়েছি, তবে আমি কোনও সরঞ্জাম জানি না যা এটি এড্রেসের সীমাতে রূপান্তর করতে পারে।


4
একটি গৌণ পার্শ্ব নোট: যদি কোনও ফাংশন চিহ্নিত করা থাকে তবে staticএটি তার কল সাইটগুলিতে সংকলক দ্বারা ইনলাইন করা হতে পারে। এর অর্থ হ'ল প্রকৃতপক্ষে পৃথকীকরণের কোনও কার্যকারিতা নেই । আপনি যদি অন্য ফাংশনগুলির জন্য চিহ্নগুলি সন্ধান করতে পারেন তবে আপনি যে ফাংশনটি সন্ধান করছেন তা নয়, এটি একটি শক্ত ইঙ্গিত যা ফাংশনটি অন্তর্ভুক্ত করা হয়েছে। Valgrind এখনও মূল প্রাক-ইনলাইনড ফাংশনটি উল্লেখ করতে পারে কারণ নির্দেশাবলী অন্য কোথাও সরিয়ে নেওয়া সত্ত্বেও ELF ফাইল ডিবাগিং তথ্য স্টোর যেখানে প্রতিটি স্বতন্ত্র নির্দেশের সূত্রপাত হয়েছিল।
ডেভিডজি

@ ডেভিডগ: সত্য, তবে যেহেতু টমের উত্তর এই ক্ষেত্রে কাজ করেছে, তাই বলে মনে হয় না। তবুও, আপনি কীভাবে উদাহরণস্বরূপ কোনও নির্দেশিকা কোথা থেকে এসেছেন সে তথ্য দিয়ে অ্যাসেম্বলি কোডটি বর্নিত করার কোনও উপায় জানেন?
এমভিজি

4
শুনে ভাল লাগলো! addr2lineথেকে পিসি / আইপি গ্রহণ করবে stdinএবং তাদের সংশ্লিষ্ট উত্স কোড লাইনগুলি মুদ্রণ করবে। একইভাবে, objdump -lউত্সড্যাম্পগুলি উত্স লাইনের সাথে মিশ্রিত করবে; ভারী ইনলাইনিং সহ উচ্চতর অপ্টিমাইজড কোডের জন্য, যে কোনও প্রোগ্রামের ফলাফল সর্বদা বিশেষভাবে সহায়ক হয় না।
ডেভিডজি

উত্তর:


87

আমি সহজ পদ্ধতির হিসাবে জিডিবি ব্যবহার করার পরামর্শ দেব। আপনি এটি ওয়ান-লাইনার হিসাবেও করতে পারেন, যেমন:

gdb -batch -ex 'file /bin/ls' -ex 'disassemble main'

4
+1 অননুমোদিত বৈশিষ্ট্য! -ex 'command'ভিতরে নেই man gdb!? তবে বাস্তবে জিডিবি ডক্সে তালিকাভুক্ত রয়েছে । অন্যদের জন্যও এই জাতীয় জিনিসগুলি /bin/lsছিনতাই করা হতে পারে, সুতরাং যদি সেই সঠিক আদেশটি কিছু না দেখায়, অন্য কোনও বস্তুর চেষ্টা করুন! ফাইল / অবজেক্টকে বেয়ারওয়ার্ড আর্গুমেন্ট হিসাবে নির্দিষ্ট করতে পারে; উদাহরণস্বরূপ,gdb -batch -ex 'disassemble main' /bin/ls
hoc_age

4
ম্যান পেজটি চূড়ান্ত নয়। দীর্ঘদিন ধরে এটি সত্যই রক্ষণাবেক্ষণ করা হয়নি তবে এখন আমি মনে করি এটি মূল ডক্স থেকে তৈরি হয়েছে। এছাড়াও "gdb --help" এখন আরও সম্পূর্ণ।
টম ট্রোমে

7
gdb /bin/ls -batch -ex 'disassemble main'পাশাপাশি কাজ করে
স্টেফ্যান্ট

4
আপনি যদি column -ts$'\t'জিডিবি আউটপুট ফিল্টার করতে ব্যবহার করেন তবে আপনার কাঁচা বাইট এবং উত্স কলামগুলি সুন্দরভাবে সাজানো থাকবে। এছাড়াও, এর -ex 'set disassembly-flavor intel'আগে অন্যান্য -exগুলি ইন্টেল অ্যাসেম্বলির সিনট্যাক্সের ফলাফল করবে।
Ruslan

আমি disassemble fnউপরের পদ্ধতিটি ব্যবহার করে ডাকলাম । তবে মনে হয় বাইনারি ফাইলটিতে একই নামের সাথে একাধিক ফাংশন উপস্থিত থাকলে কেবল একটিই আলাদা করা যায়। তাদের সমস্তকে বিচ্ছিন্ন করা কি সম্ভব বা আমার কাঁচা ঠিকানার উপর ভিত্তি করে তাদের আলাদা করা উচিত?
আহমাদ

28

disassemble/rsসোর্স এবং কাঁচা বাইটগুলিও দেখানোর জন্য জিডিবি

এই ফর্ম্যাটটি সহ, এটি সত্যিই কাছাকাছি হয় objdump -S আউটপুটটির :

gdb -batch -ex "disassemble/rs $FUNCTION" "$EXECUTABLE"

main.c

#include <assert.h>

int myfunc(int i) {
    i = i + 2;
    i = i * 2;
    return i;
}

int main(void) {
    assert(myfunc(1) == 6);
    assert(myfunc(2) == 8);
    return 0;
}

সংকলন এবং বিচ্ছিন্ন করা

gcc -O0 -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
gdb -batch -ex "disassemble/rs myfunc" main.out

বিযুক্তি:

Dump of assembler code for function myfunc:
main.c:
3       int myfunc(int i) {
   0x0000000000001135 <+0>:     55      push   %rbp
   0x0000000000001136 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x0000000000001139 <+4>:     89 7d fc        mov    %edi,-0x4(%rbp)

4           i = i + 2;
   0x000000000000113c <+7>:     83 45 fc 02     addl   $0x2,-0x4(%rbp)

5           i = i * 2;
   0x0000000000001140 <+11>:    d1 65 fc        shll   -0x4(%rbp)

6           return i;
   0x0000000000001143 <+14>:    8b 45 fc        mov    -0x4(%rbp),%eax

7       }
   0x0000000000001146 <+17>:    5d      pop    %rbp
   0x0000000000001147 <+18>:    c3      retq   
End of assembler dump.

উবুন্টু 16.04, জিডিবি 7.11.1 এ পরীক্ষিত।

জেজডাম্প + অ্যাজক ওয়ার্কআরাউন্ডস

উল্লিখিত হিসাবে অনুচ্ছেদটি মুদ্রণ করুন: /unix/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the টেক্সট

objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <FUNCTION>/'

যেমন:

objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <myfunc>/'

শুধু দেয়:

0000000000001135 <myfunc>:
    1135:   55                      push   %rbp
    1136:   48 89 e5                mov    %rsp,%rbp
    1139:   89 7d fc                mov    %edi,-0x4(%rbp)
    113c:   83 45 fc 02             addl   $0x2,-0x4(%rbp)
    1140:   d1 65 fc                shll   -0x4(%rbp)
    1143:   8b 45 fc                mov    -0x4(%rbp),%eax
    1146:   5d                      pop    %rbp
    1147:   c3                      retq   

ব্যবহার করার সময় -S, আমি মনে করি না যে কোনও ব্যর্থ-প্রমাণের উপায় আছে, কারণ কোড মন্তব্যে কোনও সম্ভাব্য ক্রম থাকতে পারে ... তবে নিম্নলিখিতগুলি প্রায় সব সময় কাজ করে:

objdump -S main.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag'

থেকে অভিযোজিত: কীভাবে দুটি মার্কার নিদর্শনগুলির মধ্যে লাইনগুলি নির্বাচন করতে হয় যা একাধিকবার ডাব্লু / এসডের সাথে ঘটতে পারে

মেইলিং তালিকা উত্তর

মেলিং তালিকায় একটি 2010 থ্রেড রয়েছে যা বলে যে এটি সম্ভব নয়: https://sourceware.org/ML/binutils/2010-04/msg00445.html

gdbটম দ্বারা প্রস্তাবিত কর্মক্ষেত্রের পাশাপাশি , তারা আরও একটি (আরও খারাপ) সংকলনের কর্মপরিকল্পনা সম্পর্কে মন্তব্য করেছে-ffunction-section কর্মক্ষেত্রের যার প্রতি বিভাগে একটি ফাংশন রাখে এবং পরে বিভাগটি ফেলে দেওয়া হয়।

নিকোলাস ক্লিফটন এটিকে একটি ডাব্লুওএনটিএফআইএক্স https://sourceware.org/ML/binutils/2015-07/msg00004.html দিয়েছে , সম্ভবত কারণ জিডিবি ওয়ার্কআরউন্ড সেই ক্ষেত্রে ব্যবহার করে।


ভাগ করা লাইব্রেরি এবং অবজেক্ট ফাইলগুলিতে জিডিবি পদ্ধতির সূক্ষ্ম কাজ করে।
টম ট্রমে

16

ওজডাম্প ব্যবহার করে একক একক ফাংশনকে বিযুক্ত করুন

আমার দুটি সমাধান রয়েছে:

কমান্ডলাইন ভিত্তিক

এই পদ্ধতিটি নিখুঁতভাবে কাজ করে এবং একটি সাধারণকে অতিরিক্ত করে তোলে। আমি -d পতাকাটি দিয়ে অ্যাজডাম্প ব্যবহার করি এবং এটি এজেডের মাধ্যমে পাইপ করি । বিচ্ছিন্ন আউটপুটটি দেখে মনে হচ্ছে looks

000000000000068a <main>:
68a:    55                      push   %rbp
68b:    48 89 e5                mov    %rsp,%rbp
68e:    48 83 ec 20             sub    $0x20,%rsp

শুরু করার জন্য, আমি অ্যাজডাম্প আউটপুটটির বর্ণনা দিয়ে শুরু করব। একটি বিভাগ বা ফাংশন একটি খালি রেখার দ্বারা পৃথক করা হয়। সুতরাং পরিবর্তন এফএস (ফিল্ড বিভাজক) কে নতুন লাইনে এবং আরএস (রেকর্ড বিভাজক) কে দ্বিগুণ নতুনরেখায় পরিবর্তন করা আপনাকে সহজেই আপনার প্রস্তাবিত ফাংশনটি অনুসন্ধান করতে দেয়, কারণ এটি কেবল $ 1 ক্ষেত্রের মধ্যে খুঁজে পাওয়া যায়!

objdump -d name_of_your_obj_file | awk -F"\n" -v RS="\n\n" '$1 ~ /main/'

অবশ্যই আপনি প্রতিস্থাপন করতে পারেন প্রধান অন্য কোন ফাংশন আপনি মুদ্রণ করতে চাই না।

2. বাশ স্ক্রিপ্ট

আমি এই ইস্যুটির জন্য একটি ছোট বাশ স্ক্রিপ্ট লিখেছি। এটি আটকান এবং অনুলিপি করুন এবং এটি যেমন দশম হিসাবে সংরক্ষণ করুন ফাইল করুন।

#!/bin/bash
# Author: abu
# filename: dasm
# Description: puts disassembled objectfile to std-out

if [ $# = 2 ]; then
        sstrg="^[[:xdigit:]]{2,}+.*<$2>:$"
        objdump -d $1 | awk -F"\n" -v RS="\n\n" '$1 ~ /'"$sstrg"'/'
elif [ $# = 1 ]; then
        objdump -d $1 | awk -F"\n" -v RS="\n\n" '{ print $1 }'
else
    echo "You have to add argument(s)"
    echo "Usage:   "$0 " arg1 arg2"  
    echo "Description: print disassembled label to std-out"
    echo "             arg1: name of object file"
    echo "             arg2: name of function to be disassembled"
    echo "         "$0 " arg1    ... print labels and their rel. addresses" 
fi

এক্স-অ্যাক্সেস পরিবর্তন করুন এবং এটির সাথে অনুরোধ করুন:

chmod +x dasm
./dasm test main

এটি স্ক্রিপ্টের সাহায্যে জিডিবি আহ্বানের চেয়ে অনেক দ্রুত। পাশাপাশি অ্যাজডাম্প ব্যবহার করে চলবে না করে গ্রন্থাগারগুলি মেমরিতে লোড এবং তাই নিরাপদ!


ভিটালি ফাদেভ এই স্ক্রিপ্টটিতে একটি স্ব-সমাপ্তির প্রোগ্রাম করেছেন, যা সত্যিই একটি দুর্দান্ত বৈশিষ্ট্য এবং টাইপিংয়ের গতি বাড়ায়।

স্ক্রিপ্ট এখানে পাওয়া যাবে


মনে হয় এটি নির্ভর করে objdumpবা gdbদ্রুত হয়। একটি বিশাল বাইনারি (ফায়ারফক্স 'libxul.so) objdumpচিরতরে লাগে, আমি এটি এক ঘন্টার পরে বাতিল করেছিলাম, gdbএক মিনিটেরও কম সময় নেয়।
সাইমন

6

আপনার যদি খুব সাম্প্রতিক বিনুটি (2.32+) থাকে তবে এটি খুব সহজ।

--disassemble=SYMBOLঅ্যাজডাম্পে পাস করা কেবলমাত্র নির্দিষ্ট ফাংশনকেই বিচ্ছিন্ন করে দেবে। প্রারম্ভিক ঠিকানা এবং শেষ ঠিকানাটি পাস করার দরকার নেই।

এলএলভিএম অ্যাজডাম্পেও অনুরূপ বিকল্প রয়েছে ( --disassemble-symbols)।


ধন্যবাদ. বাইনুটিলেস ২.৩২, ২২ শে ফেব্রুয়ারী 2019: চেঞ্জলগ : তালিকা. gnu.org/archive/html/info-gnu/2019-02/msg00000.html " ওজডাম্প -ডিসাসেম্বল অপশনটি এখন পরামিতি নিতে পারে, বিচ্ছিন্নকরণের জন্য শুরুর প্রতীকটি নির্দিষ্ট করে Dis এই প্রতীক থেকে পরবর্তী প্রতীক বা ফাংশনের শেষ
অবধি চলতে থাকবে

5

অন্যান্য উত্তরের তুলনায় অ্যাজডাম্পের আউটপুট পার্স করার জন্য অ্যাডকের ব্যবহারকে সহজ করার জন্য:

objdump -d filename | sed '/<functionName>:/,/^$/!d'

4

এটি ঠিক জিডিবি সলিউশনের মতো কাজ করে (এটি অফসেটগুলি শূন্যের দিকে বদলে দেয়) তবে এটি পিছনে নেই (আমার পিসিতে প্রায় 5 এমএসে কাজটি সম্পন্ন হয় যেখানে জিডিবি সলিউশনটি প্রায় 150 মিমি নিয়ে থাকে):

objdump_func:

#!/bin/sh
# $1 -- function name; rest -- object files
fn=$1; shift 1
exec objdump -d "$@" | 
awk " /^[[:xdigit:]].*<$fn>/,/^\$/ { print \$0 }" |
awk -F: -F' '  'NR==1 {  offset=strtonum("0x"$1); print $0; } 
                NR!=1 {  split($0,a,":"); rhs=a[2]; n=strtonum("0x"$1); $1=sprintf("%x", n-offset); printf "%4s:%s\n", $1,rhs }'

আমি এখনই পরীক্ষা করতে পারছি না, তবে আমি কখন এই দিকে ঘুরে দেখব to আপনি কি "শিফট অফসেট অফ শূন্যের দিকে" দিকটি কিছুটা ব্যাখ্যা করতে পারেন? আমি এখানে জিডিবি এর উত্তরগুলিতে এই স্পষ্ট দেখতে পাইনি, এবং সেখানে আসলে কী চলছে এবং কেন চলছে সে সম্পর্কে আমি আরও কিছু শুনতে চাই।
এমভিজি

এটি মূলত এটিকে দেখতে এমনভাবে দেখায় যে আপনি যে ফাংশনটিকে লক্ষ্য করেছেন (যা প্রথমে awkতা করে) বস্তুর ফাইলে কেবলমাত্র ফাংশন ছিল, এটি যদি ফাংশনটি শুরু হয়, এমনকি বলি 0x2d, দ্বিতীয় তীরচিহ্নটি এটিকে 0x00বিয়োগ করবে (বিয়োগ করে) 0x2dপ্রতিটি নির্দেশের ঠিকানা থেকে), যা কার্যকর কারণ সমাবেশ সভাটি প্রায়শই ফাংশন শুরু হওয়ার সাথে সম্পর্কিত করে তোলে এবং যদি ফাংশনটি 0 থেকে শুরু হয়, আপনাকে আপনার মাথার বিয়োগগুলি করতে হবে না। অ্যাজক কোডটি আরও ভাল হতে পারে তবে কমপক্ষে এটি কাজটি করে এবং মোটামুটি দক্ষ।
পিএসকোকিক

প্রত্যক্ষদৃষ্টিতে এটি মনে -ffunction-sectionsহয় যে প্রতিটি ফাংশন 0 থেকে শুরু হয় তা নিশ্চিত করার একটি সহজ উপায়
হ'ল

3

জন্য বাশ সম্পূর্ণ ./dasm

সম্পূর্ণ প্রতীক নাম থেকে এই সমাধান (ডি ল্যাঙ সংস্করণ):

  • টাইপ করে dasm testএবং তারপরে চাপ দিয়েTabTab , আপনি সমস্ত কার্যকারিতার তালিকা পাবেন।
  • টাইপ করে dasm test mএবং তারপরে মিTabTab দিয়ে শুরু করা সমস্ত ফাংশন টিপে দেখানো হবে বা কেবলমাত্র একটি ফাংশন উপস্থিত থাকলে তা স্বয়ংক্রিয়ভাবে সম্পন্ন হবে।

ফাইল /etc/bash_completion.d/dasm:

# bash completion for dasm
_dasm()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    if [[ $COMP_CWORD -eq 1 ]] ; then
    # files
    COMPREPLY=( $( command ls *.o -F 2>/dev/null | grep "^$cur" ) )

    elif [[ $COMP_CWORD -eq 2 ]] ; then
    # functions
    OBJFILE=${COMP_WORDS[COMP_CWORD-1]}

    COMPREPLY=( $( command nm --demangle=dlang $OBJFILE | grep " W " | cut -d " " -f 3 | tr "()" "  " | grep "$cur" ) )

    else
    COMPREPLY=($(compgen -W "" -- "$cur"));
    fi
}

complete -F _dasm dasm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.