Foundationপ্রথম নীতি থেকে
LEVEL 3 · Assembly Language

Stack Frame

স্ট্যাক ফ্রেম

একটা function call-এর জন্য stack-এ বরাদ্দ মেমরি-অঞ্চল — return address, saved rbp, local variable — সবই rbp-র সাপেক্ষে ঠিকানা করা।

also: prologue, epilogue

Stack নিচের দিকে বাড়ে (উচ্চ ঠিকানা থেকে নিম্ন) — push-এ rsp কমে, pop-এ বাড়ে। call return address push করে জাম্প করে (atomic, দুই মাইক্রো-ধাপ একসাথে); ret সেটা pop করে rip-এ বসায়।

Prologue (frame স্থাপন) — প্রতিটা ধাপ কারণ-সহ:

push   %rbp        ; rbp callee-saved, ব্যবহারের আগে বাঁচাও
mov    %rsp, %rbp   ; স্থির reference-point স্থাপন (rsp নড়তে থাকবে, rbp না)
sub    $N, %rsp      ; locals-এর জন্য N byte দখল করো

Epilogue — ঠিক বিপরীত ক্রমে undo:

leave   ; ≡ mov %rbp,%rsp;  pop %rbp
ret     ; return address pop → rip

Layout (rbp-র সাপেক্ষে, উচ্চ থেকে নিম্ন):

rbp+8   → return address
rbp+0   → saved rbp        (rbp এখানে)
rbp-8   → স্থানীয় ভেরিয়েবল ১
rbp-16  → স্থানীয় ভেরিয়েবল ২   (rsp এখানে হতে পারে)

Buffer overflow-র উৎস ঠিক এখানেই। Local buffer (char buf[8])-এর সীমা কোনো hardware/runtime এনফোর্স করে না — সীমা ছাড়িয়ে লেখা মানে ঠিক পরের ঠিকানায় লেখা, যেটা হতে পারে saved rbp, তারপর return address। ret অন্ধভাবে বিশ্বাস করে top-এ বৈধ ঠিকানা আছে — ওভাররাইট হলে ভুল জায়গায় জাম্প করে, সাধারণত crash। প্রতিরক্ষা: stack canary (ফেরার আগে যাচাই), ASLR (ঠিকানা random), NX bit (stack non-executable) — কোনোটাই একা নিশ্ছিদ্র না, একসাথে “defense in depth”।

-fomit-frame-pointer-এ rbp সাধারণ register হিসেবে মুক্ত হয়, locals rsp-র সাপেক্ষে (variable offset) address হয় — debugger তখন frame-pointer-chain না, আলাদা DWARF metadata দিয়ে stack unwind করে।