শেল স্ক্রিপ্ট মোড়ানো

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

মোড়ানো শেল স্ক্রিপ্ট ব্যবহার করুন

wrap.sh ব্যবহার করা সহজ:

  1. একটি কাস্টম ডিবাগযোগ্য APK কম্পাইল করুন যা নিম্নলিখিত প্যাকেজ করে:
    • wrap.sh নামে একটি শেল স্ক্রিপ্ট। আরও বিশদ বিবরণের জন্য মোড়ানো শেল স্ক্রিপ্ট এবং প্যাকেজ wrap.sh তৈরি করুন দেখুন।
    • আপনার শেল স্ক্রিপ্টের জন্য প্রয়োজনীয় যেকোন অতিরিক্ত সরঞ্জাম (যেমন আপনার নিজস্ব strace বাইনারি)।
  2. একটি ডিভাইসে ডিবাগযোগ্য APK ইনস্টল করুন।
  3. অ্যাপটি চালু করুন।

মোড়ানো শেল স্ক্রিপ্ট তৈরি করুন

আপনি যখন একটি ডিবাগযোগ্য APK চালু করেন যাতে wrap.sh থাকে, তখন সিস্টেমটি স্ক্রিপ্টটি চালায় এবং আর্গুমেন্ট হিসাবে অ্যাপটি শুরু করার কমান্ডটি পাস করে। স্ক্রিপ্টটি অ্যাপটি শুরু করার জন্য দায়ী, তবে যেকোনো পরিবেশ বা যুক্তি পরিবর্তন করতে পারে। স্ক্রিপ্টটি MirBSD কর্ন শেল (mksh) সিনট্যাক্স অনুসরণ করবে।

নিম্নলিখিত স্নিপেটটি দেখায় কিভাবে একটি সাধারণ wrap.sh ফাইল লিখতে হয় যা অ্যাপটি শুরু করে:

#!/system/bin/sh
exec "$@"

Malloc ডিবাগ

wrap.sh এর মাধ্যমে malloc ডিবাগ ব্যবহার করতে, আপনি নিম্নলিখিত লাইনটি অন্তর্ভুক্ত করবেন:

#!/system/bin/sh
LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"

আসান

ASan ডকুমেন্টেশনে ASan এর জন্য কীভাবে এটি করতে হয় তার একটি উদাহরণ রয়েছে।

প্যাকেজ wrap.sh

wrap.sh এর সুবিধা নিতে, আপনার APK ডিবাগযোগ্য হতে হবে। নিশ্চিত করুন যে android:debuggable="true" সেটিংস আপনার Android ম্যানিফেস্টের <application> উপাদানে কনফিগার করা আছে, অথবা আপনি যদি Android Studio ব্যবহার করেন যে আপনি build.gradle ফাইলে একটি ডিবাগ বিল্ড কনফিগার করেছেন।

আপনার অ্যাপের build.gradle ফাইলে useLegacyPackaging true হিসাবে সেট করাও প্রয়োজনীয়। বেশিরভাগ ক্ষেত্রে, এই বিকল্পটি ডিফল্টরূপে false সেট করা থাকে, তাই আপনি কোনো বিস্ময় এড়াতে এটিকে স্পষ্টভাবে true সেট করতে চাইতে পারেন।

আপনাকে অবশ্যই অ্যাপের নেটিভ লাইব্রেরিগুলির সাথে wrap.sh স্ক্রিপ্টটি প্যাকেজ করতে হবে৷ যদি আপনার অ্যাপে নেটিভ লাইব্রেরি না থাকে, তাহলে আপনার প্রোজেক্ট ডিরেক্টরিতে ম্যানুয়ালি lib ডিরেক্টরি যোগ করুন। আপনার অ্যাপ সমর্থন করে এমন প্রতিটি আর্কিটেকচারের জন্য, আপনাকে অবশ্যই সেই নেটিভ লাইব্রেরি ডিরেক্টরির অধীনে মোড়ানো শেল স্ক্রিপ্টের একটি অনুলিপি প্রদান করতে হবে।

নিম্নলিখিত উদাহরণটি ARMv8 এবং x86-64 উভয় আর্কিটেকচারকে সমর্থন করার জন্য ফাইল লেআউট দেখায়:

# App Directory
|- AndroidManifest.xml
|- …
|- lib
   |- arm64-v8a
      |- ...
      |- wrap.sh
   |- x86_64
      |- ...
      |- wrap.sh

অ্যান্ড্রয়েড স্টুডিও শুধুমাত্র lib/ ডিরেক্টরি থেকে .so ফাইল প্যাকেজ করে, তাই আপনি যদি একজন অ্যান্ড্রয়েড স্টুডিও ব্যবহারকারী হন, তাহলে আপনার wrap.sh ফাইলগুলিকে পরিবর্তে src/main/resources/lib/* ডিরেক্টরিতে রাখতে হবে, যাতে তারা সঠিকভাবে প্যাকেজ করা হবে.

মনে রাখবেন যে resources/lib/x86 UI-তে lib.x86 হিসাবে প্রদর্শিত হবে, কিন্তু এটি আসলে একটি সাবডিরেক্টরি হওয়া উচিত:

অ্যান্ড্রয়েড স্টুডিওতে প্যাকেজিং wrap.sh এর উদাহরণ

wrap.sh ব্যবহার করার সময় ডিবাগ করুন

wrap.sh ব্যবহার করার সময় আপনি যদি একটি ডিবাগার সংযুক্ত করতে চান, আপনার শেল স্ক্রিপ্টকে ম্যানুয়ালি ডিবাগিং সক্ষম করতে হবে। এটি কীভাবে করা যায় তা রিলিজের মধ্যে পরিবর্তিত হয়েছে, তাই এই উদাহরণটি দেখায় যে সমস্ত রিলিজের জন্য উপযুক্ত বিকল্পগুলি কীভাবে যুক্ত করা যায় যা wrap.sh সমর্থন করে:

#!/system/bin/sh

cmd=$1
shift

os_version=$(getprop ro.build.version.sdk)

if [ "$os_version" -eq "27" ]; then
  cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -eq "28" ]; then
  cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
  cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
fi

exec $cmd