A process address space is a collection of mapping regions and their permissions, not a fixed continuous partition of "code, data, heap, stack." /proc/PID/maps describes which addresses are currently mapped, while smaps supplements this with statistics on residency and sharing. Only by distinguishing virtual addresses, underlying files or anonymous storage, and actual resident pages can memory usage be correctly interpreted.
64-bit Does Not Mean All 64-bit Addresses Are Available
Pointer width, the number of address bits implemented by the CPU, kernel page table configuration, and user-space address space range are distinct concepts. x86-64 commonly uses four-level or five-level page table configurations, while arm64 has different combinations of virtual address widths and page granularities. It is incorrect to state as a cross-architecture fact that "every Linux process is 48-bit or 57-bit."
The address space contains unmapped holes, reserved regions, and ranges restricted by policy. Even after a mapping succeeds, independent physical memory is not necessarily allocated for every page; page faults, zero pages, file caches, and copy-on-write gradually determine the actual page state.
This is a manually constructed format example. The address range is half-open, with a length of 0x4000; the mapping starts from file offset 0x2000. r/w/x indicate read/write/execute permissions, p indicates private, and s indicates shared. Device numbers and inodes help identify the underlying object; the path may include "deleted," and the name itself is not a stable identity.
If the accessed address is 0x70000120, the corresponding offset for this file-backed region is 0x2000 + 0x120 = 0x2120. However, parts like .bss that do not correspond to file bytes cannot be uniformly treated as readable disk offsets. proc_pid_maps(5)
ELF files are loaded according to program header segments; you cannot map each VMA line one-to-one with a section. A single PT_LOAD may be split into multiple lines due to permission adjustments, etc. The tail of .bss may be mixed with the last page of the file, followed by anonymous zero-filled mappings. Interpret this using readelf -lW's offset, filesz, and memsz.
private Does Not Always Mean Exclusive Physical Pages
MAP_PRIVATE indicates that modifications will not be written back to other mapping users in the manner of shared mappings. Private anonymous pages after fork usually share physical content initially, copying only upon write; unmodified pages of private file mappings can also share file caches.
Therefore, ordinary private anonymous regions obtained by malloc using mmap may still undergo COW after fork. Using mmap is not a sufficient condition for "fork-friendly so no COW." For an example of MAP_SHARED where modifications are truly shared, see Shared Memory and Semaphores.
Distinguishing Private vs. Shared Modifications Using Parent and Child Processes
Below, we first create MAP_PRIVATE and MAP_SHARED anonymous mappings for two pages, write the same initial value of 7, and then fork. The child process writes 9 to both locations; the parent process waits for the child to finish and then reads. The private page remains 7, while the shared page becomes 9. Memory relationships of fork
Save as cow-demo.c, execute cc -Wall -Wextra cow-demo.c -o cow-demo, and then run it. The expected output is parent: private=7 shared=9. Parent and child processes see the same virtual pointer values, but can see different contents via private mappings; therefore, comparing address values alone cannot determine if two processes share modifications.
This example uses waitpid to confirm the child process has finished writing, ensuring the parent process does not concurrently poll during the child's write phase. Actual shared memory queues require inter-process synchronization; you cannot treat "mapping as shared" as automatically completing publish, ordering, and notification. The experiment verifies visibility semantics and cannot directly measure how many physical pages the kernel actually copied from these two bytes.
Stack: Main Thread vs. pthread Stack
The main thread stack is established during exec, often identified by [stack], and can expand on eligible page faults, subject to resource limits, adjacent mappings, and protection rules. It is not allocated by brk, and arbitrary access to addresses near the stack is not automatically accepted by the kernel.
pthread stacks are usually established by the thread library using anonymous mappings. Their size and guard policies can be adjusted via attributes, so the main stack's automatic growth model cannot be simply copied. Default sizes vary based on startup limits, platform, and thread library; they are not fixed at 8 MiB.
Ordinary unnamed anonymous VMAs may belong to thread stacks, allocator arenas, JIT, or other objects. Modern maps no longer universally display [stack:TID] for each thread stack; you cannot confirm a rw-p region is definitely a stack based solely on its position.
Heap: malloc Objects Are Not All in [heap]
[heap] usually corresponds to the traditional heap range managed by the program break. malloc also uses other anonymous mappings for arenas or large block allocations, so counting this single line does not yield the total dynamic allocation amount.
Small allocations may come from thread caches or existing free blocks in the arena, not calling brk every time. Whether to use independent mmap depends on allocation size, current free blocks, thresholds, runtime history, and the specific allocator; you cannot apply a fixed 128 KiB rule universally. malloc Internals
vDSO, vvar, and Historical vsyscall
vDSO is a small ELF code segment provided by the kernel to user space, accelerating specific calls on supported architectures and kernels; related read-only data mappings often appear as vvar. These are special kernel-provided mappings and should not be treated as ordinary malloc anonymous pages.
The set of functions, symbol versions, and whether to fall back to system calls are determined by the implementation. Even though clock_gettime often uses vDSO, you cannot infer that no clock or kernel will ever execute a syscall. Locate them via auxiliary vectors and other conventions; do not hardcode addresses. vdso(7)
The historical vsyscall on x86-64 uses a fixed address range, which may be emulated or disabled by the kernel, depending on configuration. It is not the same interface as the randomizable vDSO, and arm64 does not copy this fixed address.
Observing Your Own Actual Layout
The following program prints the addresses of several objects and reads its own maps. In cat /proc/self/maps, self refers to the cat process, not the shell that launched it; when viewing the target, use the target PID, or read it internally as done here.
After compiling, find which interval each of the three addresses falls into. The base addresses may change across independent launches, but specific address differences are not guaranteed by language semantics. Allocations that are not initialized and where every page is not accessed are not suitable as experiments for "allocating X increases RSS by exactly X."
RSS, PSS, and Virtual Size
VmSize describes the scale of the virtual address range, while RSS counts resident pages. Shared pages may be double-counted in the RSS of multiple processes. PSS apportions sharing, helping to compare the resident contribution of a group of processes. smaps_rollup provides summaries, while smaps retains per-mapping details.
These metrics still do not equal the allocator's in-use bytes, nor do they equal cgroup accounting; page tables, kernel objects, shared caches, and timing of statistics create different perspectives. Mappings and counts change as the process runs; reading across multiple /proc files does not automatically form a single atomic snapshot. Kernel /proc Documentation
Explain PSS Using Page Accounting, Not as Another malloc Size
Assume parent and child processes jointly map 4 resident pages of 4 KiB each, with no other sharers. Each process's RSS calculates the full 4 pages, while PSS calculates half per page. After the child process undergoes COW on one of these pages, leaving 3 common pages plus 1 private page each for parent and child. smaps Metrics
This model explains why, after copying occurs, RSS might show no change. Real smaps also encounters factors like changing sharers, page reclamation, huge pages, and statistical precision; do not treat this 2 KiB change as the mandatory whole-process difference that must appear in every run of cow-demo.
Reverse-Querying VMAs from Printed Addresses Requires Verifying Interval Inclusion
The global, stack, and allocated addresses from the previous program can be compared one-by-one with the start and end addresses in maps, using start ≤ address < end. If an address exactly equals end, it no longer belongs to that line. Path names can assist in explaining the mapping source but cannot replace this check, nor can they prove the object is still alive.
Address Location
Confirmed Information
Information Still Needed
Inside File Mapping
File region and permissions
ELF segments, symbols, and whether private modifications occurred
Inside [heap]
Located in traditional program break region
Which allocation object it corresponds to, and whether it has been freed
Inside Unnamed rw-p
Private writable anonymous region
Thread stack, arena, or other purposes
No Mapping
No ordinary VMA for this address at this time
Address origin, lifecycle, and mapping changes
Why Did Physical Pages Increase When RSS Didn't Change?
Treat colored blocks with the same name as two mappings to the same physical page. Each time COW occurs, the child process still maps four pages, so RSS remains unchanged; but one page is no longer shared with the parent, changing PSS from half-page accounting to full-page accounting. This only accounts for these four pages and cannot be directly equated to the difference in the real process's entire smaps.
PSS=p∈resident∑sharingcount(p)pagesize(p)
Preparing the visual
Why Did Physical Pages Increase When RSS Didn't Change?
COW splits originally shared physical pages into two private copies. The RSS of both processes can remain unchanged, while PSS and the total number of independent physical pages increase.
{"id":"cow-page-accounting","title":"Why Did Physical Pages Increase When RSS Didn't Change?","summary":"COW splits originally shared physical pages into two private copies. The RSS of both processes can remain unchanged, while PSS and the total number of independent physical pages increase.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div id=\"pages\" class=\"choices\"><button data-page=\"0\"><span data-i18n=\"write\"></span> 0</button><button data-page=\"1\"><span data-i18n=\"write\"></span> 1</button><button data-page=\"2\"><span data-i18n=\"write\"></span> 2</button><button data-page=\"3\"><span data-i18n=\"write\"></span> 3</button></div><div class=\"track-row\"><span data-i18n=\"parent\"></span><div id=\"parent\" class=\"track\"></div></div><div class=\"track-row\"><span data-i18n=\"child\"></span><div id=\"child\" class=\"track\"></div></div><div class=\"metrics\"><div><span data-i18n=\"rss\"></span><strong id=\"rss\"></strong></div><div><span data-i18n=\"pss\"></span><strong id=\"pss\"></strong></div><div><span data-i18n=\"physical\"></span><strong id=\"physical\"></strong></div><div><span data-i18n=\"copies\"></span><strong id=\"copies\"></strong></div></div><div class=\"actions\"><button id=\"reset\" data-i18n=\"reset\"></button></div><p class=\"formula\" id=\"equation\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px var(--viz-font-ui);padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 var(--viz-font-ui);overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}let copied=new Set();function draw(){const n=copied.size;cells('parent',[...'ABCD'].map(text=>({text,cls:'on'})));cells('child',[...'ABCD'].map((text,i)=>({text:copied.has(i)?text+'′':text,cls:copied.has(i)?'gold':'on'})));document.querySelectorAll('[data-page]').forEach(e=>{e.disabled=copied.has(+e.dataset.page);e.setAttribute('aria-pressed',String(e.disabled));});set('rss',16);set('pss',8+2*n);set('physical',16+4*n);set('copies',n);set('equation','PSS = (4 − '+n+') × 4/2 + '+n+' × 4 = '+(8+2*n)+' KiB');}document.querySelectorAll('[data-page]').forEach(e=>e.onclick=()=>{copied.add(+e.dataset.page);draw()});$('#reset').onclick=()=>{copied.clear();draw()};draw();","audio":false,"strings":{"child":"Child Process Mapping","copies":"Number of Copied Pages","heading":"Why Did Physical Pages Increase When RSS Didn't Change?","intro":"Click any page to have the child process write to that private page once.","parent":"Parent Process Mapping","physical":"Independent Physical Pages (KiB)","pss":"PSS per Process (KiB)","reset":"Reset","rss":"RSS per Process (KiB)","scope":"4 resident ordinary pages of 4 KiB each, only parent and child as sharers, no reclamation or huge pages. Letters identify physical page identity, not virtual addresses.","scopeLabel":"Model Scope and Conventions","write":"Child Process Write"}}
Locating Problems from Addresses
First confirm whether the faulting address has a mapping, then check permissions, owning object, offset, and lifecycle; "the address is inside an rw-p mapping" does not prove the object access is legal, as it might still be an out-of-bounds access within the same page or use-after-free.
Understanding the layout narrows the scope for locating issues, but object-level errors still require debug symbols and memory detection tools. The protective effects of randomization and execution permissions are covered in ASLR and Security Hardening.