5.5.17 · D3 · Coding › Embedded Systems & Real-Time Software › Linker scripts — memory regions, sections (.text, .data, .bs
Intuition Yeh page kya hai
Parent note ne tumhe bataya tha ki machinery kaise kaam karti hai. Yahan hum real numbers pe crank ghoomate hain . Hum fake programs ko ek fake chip mein place karenge, har address haath se calculate karenge, aur arithmetic check karenge. End tak tum kisi bhi linker script + kisi bhi set of variables ko dekh ke bol sako: "binary N bytes ki hai, RAM use M bytes hai, aur .data address X se Y tak copy hota hai."
Koi bhi symbol aane se pehle, hum parent se vocabulary fix kar lete hain taaki tum kabhi guess na karo:
ORIGIN (O ) = ek memory region ka starting physical address. Simple bolo — "shelf 1 kahaan hai."
LENGTH (L ) = us region mein kitne bytes aa sakte hain.
VMA = woh address jahan koi cheez run hoti hai (CPU jahan execute karte waqt pahunchta hai).
LMA = woh address jahan koi cheez binary image mein load/store hoti hai (Flash mein "attic" copy).
. (location counter) = ek running cursor. Jaise-jaise linker bytes place karta hai, . utne bytes aage badh jaata hai. Isko ek tape measure samjho jo sirf aage move karta hai.
Is topic mein jo bhi situation aa sakti hai woh in cells mein se ek mein fit hoti hai. Neeche diye examples mein se har ek ek ya zyada cells ko cover karta hai, aur milake sabhi cells hit ho jaate hain.
#
Cell class
Tricky cheez jo yeh test karta hai
C1
Pure .text, koi variables nahi
LMA = VMA (code in-place run hota hai)
C2
.data present hai
do addresses; Flash image ≠ RAM run
C3
.bss present hai
size record hoti hai, zero Flash bytes
C4
.data aur .bss dono saath
RAM dono stack karta hai; Flash sirf .data copy rakhta hai
C5
Zero / degenerate : empty .data ya empty .bss
_sdata == _edata; copy loop 0 baar chalta hai
C6
Limiting : region bilkul full / ek byte over
overflow detection, <= L boundary
C7
Alignment se gap force hota hai
. aage jump karta hai; sizes "sirf sum" nahi rehti
C8
Word-problem : "X add karne se kitna Flash lagega?"
.bss vs .data growth ke baare mein reasoning
C9
Exam twist : copy loop bhool gaye / KEEP drop kar diya
runtime symptom predict karo
Do constant facts jo hum har jagah use karte hain (parent ke formula callout se):
Sabhi examples ke liye humara chip hai:
O F L A S H = 0x08000000 , L F L A S H = 256 K ; O R A M = 0x20000000 , L R A M = 64 K .
(1K = 1024 bytes, toh 256K = 262144 bytes, 64K = 65536 bytes.)
Worked example Sabse simple possible program
Ek firmware jisme sirf machine code hai: .text = 4000 bytes, koi globals nahi, koi constants nahi. .text kahan load aur run hoga? Binary size kya hogi?
Forecast: padhne se pehle guess karo — kya yahan LMA aur VMA same hain?
Step 1. .text ko Flash ke start mein place karo. _stext = O_{FLASH} = \texttt{0x08000000}.
Yeh step kyun? SECTIONS block .text ko pehle > FLASH ke saath rakhta hai, toh . Flash ke ORIGIN se shuru hota hai.
Step 2. Location counter ko section size se aage badhao: . += 4000, toh _etext = 0x08000000 + 4000.
Yeh step kyun? Har placed byte tape measure . ko ek aage move karta hai.
0x08000000 + 4000 = 0x08000FA0 .
(4000 = 0xFA0 .)
Step 3. VMA aur LMA equal hain kyunki humne > FLASH use kiya AT> ke bina. Code directly Flash se execute hota hai.
Yeh step kyun? Koi relocation nahi hai — parent ki teesri galti ("VMA aur LMA hamesha same hote hain") sirf is case mein sach hai.
Verify: Flash image = 4000 + 0 + 0 = 4000 bytes ≤ 262144 . RAM used = 0 (plus stack). ✓ End address 0x08000FA0 hai 0x08000000 + 4000 — decode karo: 0xFA0 = 15\cdot256 + 10\cdot16 + 0 = 3840+160 = 4000. ✓
Worked example Do-address dance
.text = 4000 bytes. Ek global: int x = 5; → .data = 4 bytes (ek 32-bit int). _sidata (LMA), _sdata (VMA), _edata, aur binary size nikalo.
Forecast: kya .data Flash mein .text ke baad baithega, RAM mein, ya dono mein?
Step 1. .text ke baad Flash cursor 0x08000000 + 4000 = 0x08000FA0 par hai.
Kyun? Example 1 jaisa hi — .data ka load address (AT> FLASH) Flash cursor ko continue karta hai.
Toh _sidata = LOADADDR(.data) = \texttt{0x08000FA0}.
Step 2. Lekin .data ka run address > RAM use karta hai, toh uska VMA RAM ke ORIGIN se shuru hota hai:
_sdata = ADDR(.data) = O_{RAM} = \texttt{0x20000000}.
Kyun? > RAM run cursor ko RAM pe reset karta hai; AT> FLASH load cursor ko Flash mein rakhta hai. Do independent tape measures.
Step 3. 4 bytes se aage badhao: _edata = 0x20000000 + 4 = 0x20000004.
Kyun? .data 4 bytes ka hai, toh RAM cursor 4 move karta hai.
Step 4. Boot pe copy loop SIZEOF(.data)/4 = 1 iteration chalaata hai, 4-byte value 5 ko 0x08000FA0 (Flash) se 0x20000000 (RAM) mein copy karta hai.
Kyun? Parent ka startup loop for(p=&_sidata,q=&_sdata; q<&_edata;) *q++=*p++; words move karta hai jab tak q _edata tak nahi pahunch jaata.
Verify: Flash = 4000 + 4 = 4004 bytes (value 5 stored hai , toh .data Flash cost karta hai). RAM = 4 bytes. Copy count = ( 0 x 20000004 − 0 x 20000000 ) /4 = 1 . ✓
.bss Flash mein kuch store nahi karta
.text = 4000, koi .data nahi, ek int y; (uninitialized) → .bss = 4 bytes. Binary size aur RAM use nikalo.
Forecast: kya binary 4000 se badi ho jaati hai kyunki y exist karta hai?
Step 1. .bss sirf > RAM use karta hai (AT> nahi). Toh _sbss = O_{RAM} = 0x20000000, _ebss = 0x20000004.
Kyun? Flash se kuch load karne ki zaroorat nahi — koi initial value store nahi karni.
Step 2. Linker sirf size record karta hai (4 bytes), .bss ke liye zero Flash bytes emit karta hai.
Kyun? Flash mein 4 zeros store karna wasteful hai; startup loop unhe RAM mein likhta hai (parent ka .bss intuition).
Step 3. Boot zero-loop 4/4 = 1 iteration chalaata hai: *q++ = 0 jo 0x20000000 likhta hai.
Verify: Flash = 4000 + 0 = 4000 bytes (Example 1 se unchanged hai jabki y exist karta hai — mistake #1 ko kill karta hai). RAM = 4 bytes. ✓
Worked example Complete RAM layout
.text = 4000, .rodata = 200, .data = 40 bytes (10 ints), .bss = 100 bytes. Har symbol aur dono totals compute karo.
Forecast: RAM mein, kya .bss 0x20000000 se shuru hoga ya .data ke baad?
Step 1 — Flash cursor. .text phir .rodata phir .data ka LMA Flash mein stack hota hai:
.text: 0x08000000 → 0x08000FA0 (+4000).
.rodata: 0x08000FA0 → 0x08001068 (+200, 0xC8).
.data LMA: _sidata = 0x08001068.
Kyun? Flash cursor kabhi reset nahi hota; har > FLASH / AT> FLASH section append hota hai.
Step 2 — .data ke liye RAM cursor. _sdata = 0x20000000, _edata = 0x20000000 + 40 = 0x20000028.
Kyun? > RAM run cursor ko RAM ORIGIN pe reset karta hai.
Step 3 — .bss RAM mein .data ke baad aata hai. _sbss = _edata = 0x20000028, _ebss = 0x20000028 + 100 = 0x2000008C.
Kyun? RAM cursor .data aur .bss ke beech shared hai — .bss wahan se continue karta hai jahan .data khatam hua (sirf Flash aur RAM cursors alag hain; RAM ke andar sab kuch stack hota hai).
Verify: Flash = 4000 + 200 + 40 = 4240 bytes (.bss 0 contribute karta hai). RAM = 40 + 100 = 140 bytes. `_ebss - _sdata = 0x2000008C - 0x20000000 = 0x8C = 140. ✓ C o p y l oo p : 40/4=10w or d s ; z er o l oo p : 100/4=25$ words. ✓
Worked example Jab kisi section ka size zero ho
Ek program jisme .text = 4000 aur .bss = 20, lekin koi initialized globals nahi (.data = 0 bytes). _sdata aur _edata kya equal honge, aur copy loop kitni baar chalaega?
Forecast: kya boot copy loop crash ya hang karta hai jab copy karne ko kuch nahi hota?
Step 1. .data size = 0, toh _sdata = _edata (cursor move nahi karta). Dono 0x20000000 equal hain.
Kyun? Zero bytes place karne se . zero advance hota hai — start aur end coincide karte hain.
Step 2. Copy loop condition hai q < &_edata. Kyunki q at _edata se shuru hota hai, body 0 baar chalti hai.
Yeh kyun matter karta hai? Empty section koi bug nahi hai — < comparison naturally skip kar deta hai. Koi special case ki zaroorat nahi.
Step 3. .bss phir bhi zero karta hai: _sbss = 0x20000000, _ebss = 0x20000014 (+20). Zero loop 20/4 = 5 baar chalaata hai.
Verify: Flash = 4000 (koi .data image nahi). RAM = 0 + 20 = 20 . Copy iterations = ( _ e d a t a − _ s d a t a ) /4 = 0 . ✓
Worked example Overflow ki boundary
.data = 20000 bytes, .bss = 40000 bytes, stack = 4096, heap = 1024. Kya yeh 64K RAM mein fit hoga? Phir hum .bss mein ek aur int add karte hain. Ab?
Forecast: 64K 65536 hai. Jod ke guess karo ki linker error dega ya nahi.
Step 1. RAM used = 20000 + 40000 + 4096 + 1024 = 65120 bytes.
Kyun? Parent ki inequality: RAM = data + bss + stack + heap ≤ L R A M .
Step 2. L R A M = 65536 se compare karo. Slack = 65536 − 65120 = 416 bytes. Fit ho jaata hai. ✓
Kyun? 65120 ≤ 65536 , toh linker khush hai.
Step 3. .bss mein ek int (4 bytes) add karo: nayi .bss = 40004, total = 65124 ≤ 65536 . Ab bhi fit hai (slack 412).
Yeh twist kyun? Exam version mein usually stack + .bss ek doosre mein grow karte hain. Overflow force karne ke liye humhe > 416 zyada bytes chahiye honge.
Step 4 (overflow case). Maan lo .bss 40500 tak jaata hai (+500). Total = 65620 > 65536 . Linker abort karta hai:
region RAM overflowed by 84 bytes.
84 kyun? 65620 − 65536 = 84 . Exactly yahi ld print karta hai.
Verify: 65120 ≤ 65536 (fits). 65620 − 65536 = 84 (overflow amount). ✓
Worked example Jab sizes plain sum nahi rehti
.text Flash offset 4002 pe khatam hota hai (ek odd-ish size). .data (AT> FLASH) 4-byte alignment require karta hai (. = ALIGN(4)). .data ka LMA kahan land karega, aur binary mein kitne padding bytes aayenge?
Forecast: kya .data 4002 pe load hoga, ya aage bump hoga?
Step 1. .text ke baad: Flash cursor 0x08000000 + 4002 = 0x08000FA2 par hai.
Kyun? Cursor = ORIGIN + accumulated bytes.
Step 2. ALIGN(4) . ko 4 ke agle multiple tak upar round karta hai. 0xFA2 = 4002. 4002 se upar 4 ka aagla multiple 4004 hai.
Align kyun? Misaligned address se 32-bit load many cores pe fault karta hai (aur copy loop 4-byte words move karta hai). Aligning se clean word access guarantee hota hai.
padded LMA = 0 x 08000000 + 4004 = 0 x 08000 F A 4.
Step 3. Insert kiye gaye padding bytes = 4004 − 4002 = 2 . Yeh 2 bytes .bin mein real filler hain.
Isse naive sums kyun break hote hain: Flash image ab 4002 + 2 ( pad ) + size . d a t a hai, na ki sirf 4002 + size . d a t a .
Verify: ⌈ 4002/4 ⌉ ⋅ 4 = 4004 . Padding = 4004 − 4002 = 2 . ✓
Worked example Flash budget reasoning
Tumhare paas 200 bytes ka Flash headroom bacha hai. Tumhara teammate ya toh (a) static uint8_t lut[300] = {...}; (ek 300-byte initialized lookup table) ya (b) static uint8_t scratch[300]; (ek 300-byte zeroed buffer) add karna chahta hai. Kaun sa fit hoga?
Forecast: dono 300 bytes RAM ke hain. Kaun sa Flash touch karta hai?
Step 1. Option (a) initialized hai → .data mein jaata hai. Iske 300 bytes initial values Flash mein store hote hain.
Kyun? .data ka ek Flash LMA hota hai (copy source). 300 > 200 headroom → Flash mein FIT NAHI HOGA.
Step 2. Option (b) zero-initialized hai → .bss mein jaata hai. Yeh 0 Flash bytes cost karta hai (sirf size record hoti hai).
Kyun? Mistake #1 se: .bss koi bytes emit nahi karta. Flash headroom untouched → fit ho jaata hai.
Step 3. Dono runtime pe 300 bytes RAM cost karte hain, toh RAM alag se check karo — lekin Flash ka sawaal purely initialized vs zero se decide hota hai.
Verify: Flash cost (a) = 300 > 200 → fail. Flash cost (b) = 0 ≤ 200 → pass. ✓
Worked example Do classic boot bugs
(a) Engineer Reset_Handler se .data copy loop delete kar deta hai. Ek global int mode = 3; main() mein read hota hai. Usme kya value hogi? (b) KEEP(*(.isr_vector)) remove kar diya jaata hai aur link-time garbage collection on hai. Reset pe kya hota hai?
Forecast: kya (a) crash karega, ya silently misbehave karega?
Step 1 — case (a). Copy ke bina, _sdata par RAM kabhi write nahi hua. Usme jo bhi value RAM power-up par thi woh rahegi — undefined garbage , 3 nahi.
Kyun? Value 3 Flash (LMA) mein baitha hai lekin RAM mein VMA ne kabhi receive nahi kiya. Yeh parent ka "debug mein kaam karta hai, release mein break karta hai" wala bug hai.
Symptom: mode ek random number hai; behaviour har power cycle mein badalta hai. Koi crash nahi — silent corruption.
Step 2 — case (b). Koi bhi .isr_vector ko symbol se reference nahi karta, toh GC use delete kar deta hai. Flash address 0 (jo 0x08000000 se map hota hai) ab unrelated bytes rakhta hai.
Fatal kyun? Cortex-M reset pe CPU bahut pehle Flash ke words se initial stack pointer aur reset vector padhta hai. Wahan garbage hai → immediate hard fault / boot loop .
Symptom: dead board, kabhi main() tak nahi pahunchta.
Verify (conceptual): (a) → mode ≠ 3 (undefined); (b) → boot pe hard fault. Dono parent ke mistakes #2 aur #4 se match karte hain. ✓ (neeche numeric checks pehle se use ki gayi arithmetic cover karte hain.)
Recall Quick self-test
Example 4 mein _ebss kya hai? ::: 0x2000008C = 0x20000000 + 140.
Example 5 mein .data copy loop kitni baar chalaega? ::: Zero baar — _sdata == _edata.
Example 6 mein RAM kitne bytes overflow karta hai jab .bss = 40500 ho? ::: 84 bytes.
Example 7 mein ALIGN(4) ek 4002-byte .text ke baad kitne padding bytes insert karta hai? ::: 2 bytes.
Example 8 mein kaun sa option Flash headroom bachata hai? ::: (b), zeroed .bss buffer — 0 Flash cost.
Mnemonic Har example ka ek-line summary
"Flash mein .text + .rodata + .data count hota hai; RAM mein .data + .bss + stack + heap count hota hai; .bss Flash mein free hai; .data hi akela cheez hai jo do jagah rehta hai."
Parent: Linker scripts — memory regions, sections (.text, .data, .bss)
Boot copy/zero loops: Startup code & Reset_Handler
.isr_vector GC se kyun bachna chahiye: Vector table & interrupt handling
.data/.bss kahan se aate hain: Compilation pipeline — object files & relocation
Do memories ke peeche physical tradeoff: Flash vs RAM tradeoffs
RAM budget ke doosre tenants: Stack vs Heap in embedded systems
.bin mein actually kya hota hai: ELF file format & sections