ইউএনআইএক্স এবং লিনাক্স সিস্টেমের জন্য আইও tions। Are এবং এক্স ---- calls calls-তে কল করা সম্মেলনগুলি কী কী


147

নিম্নলিখিত লিঙ্কগুলি ইউএনআইএক্স (বিএসডি গন্ধ) এবং লিনাক্স উভয়ের জন্য x86-32 সিস্টেম কল কনভেনশন ব্যাখ্যা করে:

তবে ইউএনআইএক্স এবং লিনাক্স উভয়ের জন্য x86-64 সিস্টেম কল কনভেনশনগুলি কী কী?


ইউনিক্স কলিং কনভেনশনের জন্য কোনও "স্ট্যান্ডার্ড" নেই। লিনাক্স নিশ্চিত, তবে আমি নিশ্চিত যে সোলারিস, ওপেনবিএসডি, লিনাক্স এবং মিনিক্স সম্ভবত কমপক্ষে কিছুটা ভিন্ন কলিং কনভেনশন রয়েছে এবং সেগুলি সবগুলি ইউনিক্স।
আর্লজ

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

1
আপনারা দুজনেই ঠিক আছেন। আমি ফ্রিবিএসডি এবং লিনাক্সের সন্ধান করছি।
নখ

উত্তরটিতে কী রেজিস্টারগুলি অ্যাকসেস সিস্টেম কলগুলি সংরক্ষণ করা হয় সে সম্পর্কিত তথ্য থাকলে আমি প্রশংসা করব। অবশ্যই স্ট্যাক পয়েন্টারটি হ'ল, (যদি না __NR_clone কলটিতে নিয়ন্ত্রিত উপায়ে পরিবর্তন না হয়) তবে তাদের অন্য কি?
অ্যালবার্ট ভ্যান ডার হোর্স্ট

@ অ্যালবার্টভান্ডারহর্স্ট: হ্যাঁ, আমি উইকি উত্তরটি 32 বিটের বিবরণ সহ আপডেট করেছি। Bit৪ বিটটি ইতিমধ্যে সঠিক ছিল: rcx এবং r11 ধ্বংস হয়ে গেছে কারণ sysretকাজ করে, সাথে সাথে র্যাক্সকে ফেরতের মান দিয়ে প্রতিস্থাপন করা হয়। অন্যান্য সমস্ত নিবন্ধগুলি amd64 এ সংরক্ষিত আছে।
পিটার কর্ডেস

উত্তর:


230

এখানে যে কোনও বিষয়ের জন্য আরও পড়া: লিনাক্স সিস্টেম কলগুলির সংজ্ঞা নির্দেশিকা


আমি লিনাক্সে জিএনইউ এসেমব্লার (গ্যাস) ব্যবহার করে এগুলি যাচাই করেছি।

কার্নেল ইন্টারফেস

x86-32 ওরফে আই 386 লিনাক্স সিস্টেম কল কনভেনশন:

X86-32 এ লিনাক্স সিস্টেমের জন্য প্যারামিটারগুলি রেজিস্টারগুলি ব্যবহার করে পাস করা হয়। %eaxsyscall_number এর জন্য। সিস্টেম কলগুলিতে, পরামিতি পাস করার জন্য% ইবিএক্স,% এক্সএক্স,% এডিএক্স,% এসি,% এডি,% ইবিপি ব্যবহার করা হয়।

রিটার্ন মান আছে %eax। অন্যান্য সমস্ত নিবন্ধক (EFLAGS সহ) পুরো জুড়ে সংরক্ষিত আছে int $0x80

লিনাক্স অ্যাসেম্বলি টিউটোরিয়াল থেকে আমি নিম্নলিখিত স্নিপেট নিয়েছি তবে আমি এ সম্পর্কে সন্দেহজনক। কেউ যদি উদাহরণ দেখাতে পারে তবে দুর্দান্ত হবে।

যদি ছয়টিরও বেশি আর্গুমেন্ট %ebxথাকে তবে অবশ্যই মেমরির অবস্থান থাকতে হবে যেখানে আর্গুমেন্টের তালিকাটি সংরক্ষণ করা আছে - তবে এটি সম্পর্কে চিন্তা করবেন না কারণ আপনি ছয়টিরও বেশি যুক্তি সহ একটি সিস্কেল ব্যবহার করবেন না এর সম্ভাবনা কম।

উদাহরণ এবং আরও কিছু পড়ার জন্য, http://www.int80h.org/bsdasm/#alternate-calling-conferences দেখুন । আই 386 লিনাক্সের জন্য হ্যালো ওয়ার্ল্ডের আরেকটি উদাহরণ ব্যবহার করে int 0x80: হ্যালো, লিনাক্স সিস্টেমের সাথে সমাবেশ ভাষায় বিশ্ব?

32-বিট সিস্টেম কল করার আরও দ্রুত উপায় রয়েছে: ব্যবহার করে sysenter। কার্নেল sysenterনৃত্যের ব্যবহারকারী-স্থানের সাথে প্রতিটি প্রক্রিয়াতে (ভিডিএসও) মেমরির একটি পৃষ্ঠার মানচিত্র তৈরি করে, যাতে ফেরতের ঠিকানাটি সন্ধান করতে সক্ষম হওয়ার জন্য কার্নেলের সাথে সহযোগিতা করতে হবে। ম্যাপিং রেজিস্টার করতে আর্গ হিসাবে একই int $0x80। আপনার sysenterসরাসরি ব্যবহারের পরিবর্তে ভিডিএসওতে কল করা উচিত । ( ভিডিএসওতে লিঙ্ক করা এবং কল করার বিষয়ে তথ্যের জন্য এবং সিস্টেম কলগুলির সাথে করার জন্য সমস্ত কিছুর জন্য লিনাক্স সিস্টেম কলগুলির সংজ্ঞা গাইড দেখুন See sysenter)

x86-32 [ফ্রি | ওপেন | নেট | ড্রাগনফ্লাই] বিএসডি ইউনিক্স সিস্টেম কল কনভেনশন:

স্ট্যাকের উপর প্যারামিটারগুলি পাস করা হয়। স্ট্যাকের উপর প্যারামিটারগুলি (সর্বশেষ প্যারামিটারটি প্রথমে ধাক্কা দেওয়া) পুশ করুন। তারপরে অতিরিক্ত 32-বিট ডামি ডেটা চাপুন (এটি আসলে ডামি ডেটা নয় more আরও তথ্যের জন্য নিম্নলিখিত লিঙ্কটি দেখুন) এবং তারপরে একটি সিস্টেম কল নির্দেশ দিনint $0x80

http://www.int80h.org/bsdasm/#default-calling-convention


x86-64 লিনাক্স সিস্টেম কল কনভেনশন:

x86-64 ম্যাক ওএস এক্স একই তবে ভিন্ন । টোডো: বিএসডি কি করে তা পরীক্ষা করে দেখুন।

বিভাগটি দেখুন: সিস্টেম ভি অ্যাপ্লিকেশন বাইনারি ইন্টারফেস এএমডি 64 আর্কিটেকচার প্রসেসরের পরিপূরক এর "A.2 AMD64 লিনাক্স কার্নেল কনভেনশনস" । I386 এবং x86-64 সিস্টেম ভি PSABI- র সর্বশেষ সংস্করণগুলি এবিআই রক্ষণাবেক্ষণকারীটির রেপোতে এই পৃষ্ঠা থেকে লিঙ্কযুক্ত পাওয়া যাবে । (এছাড়াও দেখুন আপ-টু-ডেট এবিআই লিঙ্কগুলির জন্য ট্যাগ উইকি এবং x86 এএসএম সম্পর্কিত আরও অনেক ভাল জিনিস)

এই বিভাগ থেকে স্নিপেট এখানে:

  1. ব্যবহারকারী-স্তরের অ্যাপ্লিকেশনগুলি% rdi,% rsi,% rdx,% rcx,% r8 এবং% r9 অনুক্রমটি পাস করার জন্য পূর্ণসংখ্যা নিবন্ধ হিসাবে ব্যবহার করে। কার্নেল ইন্টারফেসটি% rdi,% rsi,% rdx,% r10,% r8 এবং% r9 ব্যবহার করে।
  2. syscallনির্দেশের মাধ্যমে একটি সিস্টেম-কল করা হয় । এই ক্লোবারগুলি% আরসিএক্স এবং% আর 11 পাশাপাশি% র্যাক্স রিটার্ন মান, তবে অন্যান্য নিবন্ধগুলি সংরক্ষিত রয়েছে।
  3. সিস্কাল নম্বরটি% রেক্স রেজিস্টারে পাস করতে হবে।
  4. সিস্টেম-কলগুলি ছয়টি আর্গুমেন্টের মধ্যে সীমাবদ্ধ, স্ট্যাকের কোনও যুক্তি সরাসরি পাস করা হয় না।
  5. সিস্কেল থেকে ফিরে,% rax রেজিস্টারে সিস্টেম কলের ফলাফল রয়েছে। -4095 এবং -1 এর মধ্যে সীমার মান একটি ত্রুটি নির্দেশ করে, এটি -errno
  6. কেবলমাত্র INTEGER বা MEMORY ক্লাসের মানগুলি কার্নেলে প্রেরণ করা হয়।

মনে রাখবেন এটি লিনাক্স-সংক্রান্ত পরিশিষ্ট থেকে এবিআইয়ের, এবং এমনকি লিনাক্সের জন্য এটি তথ্যগত নয়। (তবে এটি সত্যই সঠিক))

এই 32-বিট int $0x80ABI- র হয় (কিন্তু অত্যন্ত প্রস্তাবিত নয়) 64-বিট কোডে ব্যবহারযোগ্য। আপনি যদি 32-বিট ইন্ট 0x80 লিনাক্স এবিআই 64-বিট কোড ব্যবহার করেন তবে কি হবে? এটি এখনও এর ইনপুটগুলি 32-বিটে ছাঁটাই করে, তাই এটি পয়েন্টারগুলির পক্ষে অনুপযুক্ত এবং এটি r8-r11 শূন্য করে।

ইউজার ইন্টারফেস: ফাংশন কলিং

x86-32 ফাংশন কলিং কনভেনশন:

X86-32 এ প্যারামিটারগুলি স্ট্যাকের উপর দিয়ে গেছে। সমস্ত পরামিতিগুলি সম্পন্ন না করা এবং তারপরে callনির্দেশনা কার্যকর না হওয়া পর্যন্ত সর্বশেষ প্যারামিটারটি প্রথমে স্ট্যাকের দিকে ধাক্কা দেওয়া হয়েছিল। এটি সমাবেশ থেকে লিনাক্সে সি লাইব্রেরি (libc) ফাংশন কল করার জন্য ব্যবহৃত হয়।

I386 সিস্টেম ভি এবিআই (লিনাক্সে ব্যবহৃত) এর আধুনিক সংস্করণগুলির জন্য x86-64 সিস্টেম ভি এবিআইর মতো বরাবরই আবশ্যক যেমন, এর %espআগে 16-বাইট প্রান্তিককরণ callপ্রয়োজন। কলিগুলিকে এটি ধরে নিতে এবং এসইএসই 16-বাইট লোড / স্টোর যে সাইন ইন না করা রয়েছে সেগুলি ব্যবহার করার অনুমতি দেওয়া হয়। তবে historতিহাসিকভাবে, লিনাক্সের জন্য কেবল 4-বাইট স্ট্যাক সারিবদ্ধকরণ প্রয়োজন, তাই এটি 8-বাইট doubleবা অন্য কোনও কিছুর জন্য প্রাকৃতিকভাবে সংযুক্ত স্থান সংরক্ষণ করতে অতিরিক্ত কাজও লাগল ।

কিছু অন্যান্য আধুনিক 32-বিট সিস্টেমে 4 বাইট স্ট্যাক সারিবদ্ধকরণের এখনও দরকার নেই।


x86-64 সিস্টেম ভি ব্যবহারকারী-স্পেস ফাংশন কলিং কনভেনশন:

x86-64 সিস্টেম ভি রেজিস্টারগুলিতে অর্গগুলি পাস করে যা i386 সিস্টেম ভি এর স্ট্যাক আরগস কনভেনশন থেকে বেশি দক্ষ। এটি মেমরির (ক্যাশে) আরগগুলি সংরক্ষণ করার এবং তারপরে এটিকে আবার ক্যালিতে আবার লোড করার বিলম্ব এবং অতিরিক্ত নির্দেশাবলী এড়িয়ে চলে। এটি আরও ভালভাবে কাজ করে কারণ আরও রেজিস্টার উপলব্ধ রয়েছে এবং আধুনিক উচ্চ-পারফরম্যান্স সিপিইউগুলির পক্ষে আরও ভাল যেখানে ল্যাটেন্সি এবং অফ-অর্ডার কার্যকর করার বিষয়টি রয়েছে। (আই 386 এবিআই খুব পুরানো)।

এই নতুন পদ্ধতিতে: প্রথম প্যারামিটারগুলি ক্লাসে বিভক্ত। প্রতিটি প্যারামিটারের শ্রেণি নির্ধারণ করে যে এটি কল করা ফাংশনে কীভাবে প্রেরণ করা হয়।

সম্পূর্ণ তথ্যের জন্য দেখুন: সিস্টেম ভি অ্যাপ্লিকেশন বাইনারি ইন্টারফেস এএমডি 64 আর্কিটেকচার প্রসেসর পরিপূরক এর "3.2 ফাংশন কলিং সিকোয়েন্স" যা অংশটি পড়ে:

একবার আর্গুমেন্ট শ্রেণিবদ্ধ করা হয়, নিবন্ধগুলি নিম্নলিখিত হিসাবে পাস করার জন্য (বাম থেকে ডান ক্রমে) বরাদ্দ দেওয়া হয়:

  1. ক্লাসটি যদি স্মৃতিচিহ্ন হয় তবে স্ট্যাকের উপর আর্গুমেন্টটি পাস করুন।
  2. ক্লাসটি যদি ইন্টিগের হয় তবে% rdi,% rsi,% rdx,% rcx,% r8 এবং% r9 এর পরবর্তী উপলব্ধ রেজিস্টার ব্যবহার করা হবে

সুতরাং %rdi, %rsi, %rdx, %rcx, %r8 and %r9রেজিস্টার হয় অনুক্রমে সমাবেশ থেকে কোন libc ফাংশন পূর্ণসংখ্যা / পয়েন্টার (অর্থাত পূর্ণসংখ্যা বর্গ) পরামিতি পাস করতেন। % rdi প্রথম INTEGER প্যারামিটারের জন্য ব্যবহৃত হয়। 2 য় জন্য% rsi, 3 য় জন্য% rdx এবং আরও অনেক কিছু। তারপরে callনির্দেশ দেওয়া উচিত। কার্যকর করার সময় স্ট্যাকটি ( %rsp) অবশ্যই 16 বি-এ্যালাইন্টড থাকতে হবে call

যদি 6 টিরও বেশি INTEGER প্যারামিটার থাকে তবে 7 তম INTEGER পরামিতি এবং পরে স্ট্যাকের উপর দিয়ে দেওয়া হয়। (কলার পপস, x86-32 এর মতো।)

প্রথম 8 ভাসমান পয়েন্ট আরগগুলি% xmm0-7 এ পরে স্ট্যাকের পরে পাস করা হয়। কোনও কল-সংরক্ষিত ভেক্টর নিবন্ধ নেই। (এফপি এবং পূর্ণসংখ্যার যুক্তিগুলির মিশ্রণ সহ একটি ফাংশনে মোট 8 টিরও বেশি নিবন্ধক যুক্তি থাকতে পারে))

ভারিয়াদিক ফাংশনগুলির ( যেমনprintf ) সর্বদা প্রয়োজন %al= এফপি নিবন্ধের আর্গগুলির সংখ্যা।

rdx:raxমেমরিতে রেজিস্টারগুলিতে স্ট্রাক্ট কখন প্যাক করবেন ( রিটার্নে) এর বিধি রয়েছে । বিশদ বিবরণের জন্য এবিআই দেখুন এবং আপনার কোড কীভাবে পাস / ফিরিয়ে দেওয়া উচিত সে সম্পর্কে কম্পাইলারগুলির সাথে একমত হয় তা নিশ্চিত করার জন্য সংকলক আউটপুট পরীক্ষা করে দেখুন।


নোট করুন যে উইন্ডোজ এক্স 64 ফাংশন কলিং কনভেনশনের x86-64 সিস্টেম ভি থেকে একাধিক উল্লেখযোগ্য পার্থক্য রয়েছে, যেমন ছায়া স্পেস যা অবশ্যই কলার দ্বারা সংরক্ষণ করা উচিত (রেড-জোনের পরিবর্তে), এবং কল-সংরক্ষিত xmm6-xmm15। আরগো যার মধ্যে কোন রেজিস্টারে যায় তার জন্য খুব আলাদা নিয়ম।


1
লিনাক্স 32-তে "axx bx cd dx si di bp ব্যতীত সমস্ত নিবন্ধগুলি সংরক্ষিত আছে"। আমি কারও কথা ভাবতে পারি না ...
অ্যালবার্ট ভ্যান ডার হোর্স্ট

এএমডি On64-তে, যদি 6 টিরও বেশি পরামিতি থাকে এবং সেগুলি স্ট্যাকের উপর দিয়ে যায়, কল, কলার বা কলির পরে স্ট্যাকটি পরিষ্কার করার দায় কে?
নিকোলাস

1
@ নিকোলস: কলার স্ট্যাকটি সাফ করে। আমি ফাংশন-কলিং কনভেনশন সম্পর্কে আরও বিশদ সহ উত্তর আপডেট করেছি।
পিটার কর্ডস

1
আপনি যদি int 0x80Linux৪-বিট কোডে লিনাক্সের এবিআই ব্যবহার করেন তবে ঠিক এটি ঘটে: স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ৪60০৮7730০০/২ । এটি r8-r11 শূন্য করে এবং 32-বিট প্রসেসে চালানোর সময় ঠিক এর মতো কাজ করে। প্রশ্নোত্তরে আমার কাছে এটি কাজ করে দেখানো বা পয়েন্টার কেটে ফেলতে ব্যর্থ হওয়ার একটি উদাহরণ রয়েছে। এটি কেন এমনভাবে আচরণ করে তা দেখানোর জন্য আমি কার্নেল উত্সেও খনন করেছি।
পিটার কর্ডস

1
@ ইভানক্রোল: স্নিপেট (উদ্ধৃত পাঠ্য) লিঙ্কে লিনাক্স অ্যাসেমব্লিউ টিউটোরিয়ালটি বিশেষত বিভাগের ৪.৩
মাইকেল পেচ ২

14

সম্ভবত আপনি x86_64 এবিআই খুঁজছেন?

যদি আপনি ঠিক সেই পরে না হন তবে বিকল্প রেফারেন্সগুলি খুঁজে পেতে আপনার পছন্দসই অনুসন্ধান ইঞ্জিনে 'x86_64 অ্যাবি' ব্যবহার করুন।


5
আসলে, আমি কেবল সিস্টেম কল কনভেনশন চাই। ইউএনআইএক্স (ফ্রিবিএসডি) এর জন্য esp
নখ

3
@ ক্লাউস: সিস্টেম কল কনভেনশন এবিআইয়ের একটি অংশ one
জোনাথন লেফলার

1
হাঁ। আমি প্রতিটি স্বতন্ত্র ওএসের কার্নেল ডেভলপমেন্ট রিকে গিয়েছি এবং তাদের এটি সম্পর্কে জিজ্ঞাসা করেছি। তারা আমাকে উত্সটি অনুসন্ধান করতে এবং খুঁজে বের করতে বলেছে। আমি স্টাফ দলিল না করে বুঝতে পারি না তারা কীভাবে কেবল বিকাশ শুরু করবে? সুতরাং, আমি অন্যদের বিশদ বিশদটি পূরণ করার আশা করে আমার সংগ্রহ করা তথ্য থেকে একটি উত্তর যুক্ত করেছি।
নখর

@ জোনাথনলফলার লিঙ্কটি এখনই কাজ করছে না বলে মনে হচ্ছে। আপনি যদি লিঙ্কটি পরিদর্শন করে কোনও সমস্যা পেয়ে থাকেন তবে দয়া করে এটি আপডেট করতে পারেন?
অজয় ব্রহ্মক্ষত্রিয়

@ অজয়ব্রাহ্মক্ষত্রিয়া: মাথা উঁচু করার জন্য ধন্যবাদ; আমি ওয়েব্যাক মেশিন রেকর্ডে একটি লিঙ্ক যুক্ত করেছি। পুরো x86-64.org ওয়েবসাইটটি কোনও ডেটার সাথে সাড়া দেয়নি।
জোনাথন লেফলার

11

কলিং কনভেনশনগুলি সংজ্ঞায়িত করে যে কীভাবে রেজিস্টারগুলিতে কল করা বা অন্য প্রোগ্রাম দ্বারা কল করার সময় প্যারামিটারগুলি কীভাবে পাস হয়। এবং এই কনভেনশনের সেরা উত্স হ'ল এই হার্ডওয়্যারগুলির জন্য সংজ্ঞায়িত এবিআই মান আকারে। সংকলনের স্বাচ্ছন্দ্যের জন্য একই এবিআই ব্যবহারকারীর স্থান এবং কার্নেল প্রোগ্রাম দ্বারা ব্যবহৃত হয়। লিনাক্স / ফ্রিবিএসডি x86-64 এর জন্য একই এবিআই এবং 32-বিটের জন্য অন্য সেটটি অনুসরণ করে। তবে উইন্ডোজের জন্য x86-64 এবিআই লিনাক্স / ফ্রিবিএসডি থেকে পৃথক। এবং সাধারণত এবিআই সিস্টেম কল বনাম সাধারণ "ফাংশন কল" পার্থক্য করে না। যেমন, এখানে x86_64 কলিং কনভেনশনের একটি বিশেষ উদাহরণ এবং এটি লিনাক্স ব্যবহারকারী স্পেস এবং কার্নেল উভয়ের ক্ষেত্রে একই: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 / (প্যারামিটারগুলির ক্রম a, b, c, d, e, f নোট করুন):

ব্যবহারের রেজিস্ট্রেশন বনাম কনভেনশনগুলির একটি ভাল রেন্ডারিং

পারফরম্যান্স এই এবিআইয়ের অন্যতম কারণ (যেমন, মেমরির স্ট্যাকগুলিতে সংরক্ষণের পরিবর্তে নিবন্ধগুলির মাধ্যমে প্যারামিটারগুলি পাস করা)

এআরএমের জন্য বিভিন্ন এবিআই রয়েছে:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

এআরএম convention64 সম্মেলন:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

পাওয়ারপিসিতে লিনাক্সের জন্য:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

এবং এম্বেডের জন্য পিপিসি ইএবিআই রয়েছে:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

এই নথিটি বিভিন্ন কনভেনশনগুলির ভাল ওভারভিউ:

http://www.agner.org/optimize/calling_conventions.pdf


পুরোপুরি বিন্দু ছাড়াও। প্রশ্নের পোস্টারটি লিনাক্সে bit৪ বিট সিস্কল কলিং কনভেনশনের জন্য জিজ্ঞাসা করবে না যদি এটি সাধারণ এবিআই রূপান্তরগুলির তুলনায় একই রকম হয়।
অ্যালবার্ট ভ্যান ডার হোর্স্ট

6

লিনাক্স কার্নেল 5.0 উত্স মন্তব্য

আমি জানতাম যে x86 নির্দিষ্টকরণগুলি অধীনে রয়েছে arch/x86, এবং সেই সিস্কাল স্টাফগুলি এর অধীনে চলে arch/x86/entry। সুতরাং ডিরেক্টরিতে একটি দ্রুত git grep rdiআমাকে খিলান / x86 / এন্ট্রি / এন্ট্রি_64.S দিকে নিয়ে যায় :

/*
 * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
 *
 * This is the only entry point used for 64-bit system calls.  The
 * hardware interface is reasonably well designed and the register to
 * argument mapping Linux uses fits well with the registers that are
 * available when SYSCALL is used.
 *
 * SYSCALL instructions can be found inlined in libc implementations as
 * well as some other programs and libraries.  There are also a handful
 * of SYSCALL instructions in the vDSO used, for example, as a
 * clock_gettimeofday fallback.
 *
 * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
 * then loads new ss, cs, and rip from previously programmed MSRs.
 * rflags gets masked by a value from another MSR (so CLD and CLAC
 * are not needed). SYSCALL does not save anything on the stack
 * and does not change rsp.
 *
 * Registers on entry:
 * rax  system call number
 * rcx  return address
 * r11  saved rflags (note: r11 is callee-clobbered register in C ABI)
 * rdi  arg0
 * rsi  arg1
 * rdx  arg2
 * r10  arg3 (needs to be moved to rcx to conform to C ABI)
 * r8   arg4
 * r9   arg5
 * (note: r12-r15, rbp, rbx are callee-preserved in C ABI)
 *
 * Only called from user space.
 *
 * When user can change pt_regs->foo always force IRET. That is because
 * it deals with uncanonical addresses better. SYSRET has trouble
 * with them due to bugs in both AMD and Intel CPUs.
 */

এবং খিলান / x86 / এন্ট্রি / এন্ট্রি_32.S এ 32-বিটের জন্য :

/*
 * 32-bit SYSENTER entry.
 *
 * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
 * if X86_FEATURE_SEP is available.  This is the preferred system call
 * entry on 32-bit systems.
 *
 * The SYSENTER instruction, in principle, should *only* occur in the
 * vDSO.  In practice, a small number of Android devices were shipped
 * with a copy of Bionic that inlined a SYSENTER instruction.  This
 * never happened in any of Google's Bionic versions -- it only happened
 * in a narrow range of Intel-provided versions.
 *
 * SYSENTER loads SS, ESP, CS, and EIP from previously programmed MSRs.
 * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
 * SYSENTER does not save anything on the stack,
 * and does not save old EIP (!!!), ESP, or EFLAGS.
 *
 * To avoid losing track of EFLAGS.VM (and thus potentially corrupting
 * user and/or vm86 state), we explicitly disable the SYSENTER
 * instruction in vm86 mode by reprogramming the MSRs.
 *
 * Arguments:
 * eax  system call number
 * ebx  arg1
 * ecx  arg2
 * edx  arg3
 * esi  arg4
 * edi  arg5
 * ebp  user stack
 * 0(%ebp) arg6
 */

glibc 2.29 লিনাক্স x86_64 সিস্টেম কল বাস্তবায়ন

এখন আসুন একটি বড় libc বাস্তবায়ন দেখে প্রতারণা করুন এবং দেখুন তারা কী করছে।

এই উত্তরটি লেখার সাথে সাথে আমি এখনই ব্যবহার করছি এমন গ্লাবসি দেখার চেয়ে আরও ভাল কী হতে পারে? :-)

গ্লিবসি ২.২৯ x86_64 সিস্কেলগুলিতে সংজ্ঞা দেয় sysdeps/unix/sysv/linux/x86_64/sysdep.hএবং এতে কিছু আকর্ষণীয় কোড রয়েছে, যেমন:

/* The Linux/x86-64 kernel expects the system call parameters in
   registers according to the following table:

    syscall number  rax
    arg 1       rdi
    arg 2       rsi
    arg 3       rdx
    arg 4       r10
    arg 5       r8
    arg 6       r9

    The Linux kernel uses and destroys internally these registers:
    return address from
    syscall     rcx
    eflags from syscall r11

    Normal function call, including calls to the system call stub
    functions in the libc, get the first six parameters passed in
    registers and the seventh parameter and later on the stack.  The
    register use is as follows:

     system call number in the DO_CALL macro
     arg 1      rdi
     arg 2      rsi
     arg 3      rdx
     arg 4      rcx
     arg 5      r8
     arg 6      r9

    We have to take care that the stack is aligned to 16 bytes.  When
    called the stack is not aligned since the return address has just
    been pushed.


    Syscalls of more than 6 arguments are not supported.  */

এবং:

/* Registers clobbered by syscall.  */
# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

#undef internal_syscall6
#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
({                                  \
    unsigned long int resultvar;                    \
    TYPEFY (arg6, __arg6) = ARGIFY (arg6);              \
    TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \
    TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \
    TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \
    TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \
    TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \
    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;            \
    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \
    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \
    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \
    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \
    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \
    asm volatile (                          \
    "syscall\n\t"                           \
    : "=a" (resultvar)                          \
    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \
      "r" (_a5), "r" (_a6)                      \
    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \
    (long int) resultvar;                       \
})

যা আমি নিজেকে স্বচ্ছ বর্ণনামূলক বলে মনে করি। এটি কীভাবে নিয়মিত সিস্টেম ভি এএমডি 64 এবিআই ফাংশনের কলিং কনভেনশনের সাথে ঠিকঠাকভাবে তৈরি করা হয়েছে বলে মনে করুন নোট: https://en.wikedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions

ক্লোবারগুলির দ্রুত অনুস্মারক:

  • ccমানে পতাকা নিবন্ধকরা। তবে পিটার কর্ডেস মন্তব্য করেছেন যে এটি এখানে অপ্রয়োজনীয়।
  • memory মানে একটি পয়েন্টার সমাবেশে পাস হতে পারে এবং মেমরি অ্যাক্সেস করতে ব্যবহৃত হতে পারে

স্ক্র্যাচ থেকে একটি সুস্পষ্ট ন্যূনতম চলমান উদাহরণের জন্য এই উত্তরটি দেখুন: ইনলাইন অ্যাসেমব্লিতে সিন্যাসারের মাধ্যমে কীভাবে একটি সিস্টেম কল শুরু করা যায়?

ম্যানুয়ালি অ্যাসেমব্লিতে কিছু সিস্কেল করুন

খুব বৈজ্ঞানিক নয়, তবে মজাদার:

  • x86_64.S

    .text
    .global _start
    _start:
    asm_main_after_prologue:
        /* write */
        mov $1, %rax    /* syscall number */
        mov $1, %rdi    /* stdout */
        mov $msg, %rsi  /* buffer */
        mov $len, %rdx  /* len */
        syscall
    
        /* exit */
        mov $60, %rax   /* syscall number */
        mov $0, %rdi    /* exit status */
        syscall
    msg:
        .ascii "hello\n"
    len = . - msg
    

    গিটহাব উজানের দিকে

aarch64

আমি এখানে একটি ন্যূনতম চালনার যোগ্য ইউজারল্যান্ড উদাহরণ দেখিয়েছি: /reverseengineering/16917/arm64-syscalls-table/18834#18834 TODO গ্রেপ কার্নেল কোড এখানে সহজ হওয়া উচিত।


1
"cc"(লিনাক্সের syscalls সংরক্ষণ / RFLAGS পুনঃস্থাপিত করো: কুপোকাত করা অপ্রয়োজনীয় syscall/sysret নির্দেশাবলী R11 ব্যবহার করে, এবং কার্নেল সংরক্ষিত R11 সংশোধন না / মাধ্যমে ছাড়া অন্য RFLAGS না ptraceডিবাগার সিস্টেম কল।) এমন নয় যে এটা কখনও গুরুত্বপূর্ণ, কারণ একটি "cc"কঠোর সমালোচনা করা হয় GNU C প্রসারিত asm এ x86 / x86-64 এর জন্য অন্তর্ভুক্ত, সুতরাং আপনি এটিকে রেখে কিছু অর্জন করতে পারবেন না।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.