frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

A worker fell into a nuclear reactor pool

https://www.nrc.gov/reading-rm/doc-collections/event-status/event/2025/20251022en?brid=vscAjql9kZ...
122•nvahalik•1h ago•79 comments

Pico-Banana-400k

https://github.com/apple/pico-banana-400k
28•dvrp•44m ago•2 comments

The Linux Boot Process: From Power Button to Kernel

https://www.0xkato.xyz/linux-boot/
95•0xkato•3h ago•33 comments

California invests in battery energy storage, leaving rolling blackouts behind

https://www.latimes.com/environment/story/2025-10-17/california-made-it-through-another-summer-wi...
191•JumpCrisscross•6h ago•153 comments

The Journey Before main()

https://amit.prasad.me/blog/before-main
154•amitprasad•7h ago•56 comments

I'm drowning in AI features I never asked for and I hate it

https://www.makeuseof.com/ai-features-being-rammed-down-our-throats/
130•gnabgib•2h ago•64 comments

Show HN: Diagram as code tool with draggable customizations

https://github.com/RohanAdwankar/oxdraw
121•RohanAdwankar•6h ago•23 comments

D2: Diagram Scripting Language

https://d2lang.com/tour/intro/
46•benzguo•4h ago•7 comments

How programs get run: ELF binaries (2015)

https://lwn.net/Articles/631631/
62•st_goliath•5h ago•1 comments

Agent Lightning: Train agents with RL (no code changes needed)

https://github.com/microsoft/agent-lightning
56•bakigul•6h ago•7 comments

An Update on TinyKVM

https://fwsgonzo.medium.com/an-update-on-tinykvm-7a38518e57e9
76•ingve•5h ago•16 comments

Doctor Who archive expert shares positive update on missing episode

https://www.radiotimes.com/tv/sci-fi/doctor-who-missing-episodes-update-teases-announcement-newsu...
49•gnabgib•6d ago•25 comments

Show HN: Shadcn/UI theme editor – Design and share Shadcn themes

https://shadcnthemer.com
83•miketromba•6h ago•22 comments

ARM Memory Tagging: how it improves C/C++ memory safety (2018) [pdf]

https://llvm.org/devmtg/2018-10/slides/Serebryany-Stepanov-Tsyrklevich-Memory-Tagging-Slides-LLVM...
47•fanf2•6h ago•16 comments

Rock Tumbler Instructions

https://rocktumbler.com/tips/rock-tumbler-instructions/
152•debo_•10h ago•75 comments

An Efficient Implementation of SELF (1989) [pdf]

https://courses.cs.washington.edu/courses/cse501/15sp/papers/chambers.pdf
36•todsacerdoti•5h ago•18 comments

AI, Wikipedia, and uncorrected machine translations of vulnerable languages

https://www.technologyreview.com/2025/09/25/1124005/ai-wikipedia-vulnerable-languages-doom-spiral/
63•kawera•6h ago•31 comments

We do not have sufficient links to the UK for Online Safety Act to be applicable

https://libera.chat/news/advised
202•todsacerdoti•9h ago•61 comments

WebDAV isn't dead yet

https://blog.feld.me/posts/2025/09/webdav-isnt-dead-yet/
104•toomuchtodo•1d ago•55 comments

In memory of the Christmas Island shrew

https://news.mongabay.com/2025/10/in-memory-of-the-christmas-island-shrew/
52•hexhowells•6h ago•16 comments

Belittled Magazine: Thirty years after the Sokal affair

https://thebaffler.com/salvos/belittled-magazine-robbins
35•Hooke•5h ago•24 comments

Ubios: China's Alternative to UEFI

https://pbxscience.com/ubios-chinas-alternative-to-uefi-and-the-new-era-of-firmware-standards/
12•1970-01-01•2d ago•5 comments

Passwords and Power Drills

https://google.github.io/building-secure-and-reliable-systems/raw/ch01.html#on_passwords_and_powe...
52•harporoeder•4d ago•15 comments

Testing out BLE beacons with BeaconDB

https://blog.matthewbrunelle.com/testing-out-ble-beacons-with-beacondb/
40•zdw•6h ago•12 comments

Show HN: LLM Rescuer – Fixing the billion dollar mistake in Ruby

https://github.com/barodeur/llm_rescuer
65•barodeur•1d ago•10 comments

Making a micro Linux distro (2023)

https://popovicu.com/posts/making-a-micro-linux-distro/
156•turrini•13h ago•27 comments

Project Amplify: Powered footwear for running and walking

https://about.nike.com/en/newsroom/releases/nike-project-amplify-official-images
49•justinmayer•6h ago•35 comments

Tarmageddon: RCE vulnerability highlights challenges of open source abandonware

https://edera.dev/stories/tarmageddon
65•vsgherzi•3d ago•30 comments

Honda's ASIMO (2021)

https://www.robotsgottalents.com/post/asimo
34•nothrowaways•6h ago•9 comments

The future of Python web services looks GIL-free

https://blog.baro.dev/p/the-future-of-python-web-services-looks-gil-free
180•gi0baro-dev•6d ago•75 comments
Open in hackernews

The Journey Before main()

https://amit.prasad.me/blog/before-main
154•amitprasad•7h ago

Comments

hagbard_c•6h ago
On the subject of symbols:

> Yeah, that’s it. Now, 2308 may be slightly bloated because we link against musl instead of glibc, but the point still stands: There’s a lot of stuff going on behind the scenes here.

Slightly bloated is a slight understatement. The same program linked to glibc tops at 36 symbols in .symtab:

    $ readelf -a hello|grep "'.symtab'"
    Symbol table '.symtab' contains 36 entries:
amitprasad•6h ago
Ah I should have taken the time to verify; It might also have something to do with the way I was compiling / cross-compiling for RISC-V!

More generally, I'm not surprised at the symtab bloat from statically-linking given the absolute size increase of the binary.

vbezhenar•6h ago
I wonder how many C projects prefer to avoid standard library, just invoking Linux syscalls directly. Much more fun to write software this way, IMO.
forrestthewoods•6h ago
You had me with “avoid C standard library” but lost me at “incoming Linux syscalls directly”.

Windows support is a requirement, and no WSL2 doesn’t count.

C standard library is pretty bad and it’d be great if not using it was a little easier and more common.

pmc00•5h ago
You can do this in Windows too, useful if you want tiny executables that use minimum resources.

I wrote this little systemwide mute utility for Windows that way, annoying to be missing some parts of the CRT but not bad, code here: https://github.com/pablocastro/minimute

gpm•5h ago
I thought windows had an unstable syscall interface?
LegionMammal978•5h ago
It looks like that project does link against the usual Windows DLLs, it just doesn't use a static or dynamic C runtime.
pmc00•5h ago
Windows isn’t quite like Linux in that typically apps don’t make syscalls directly. Maybe you could say what’s in ntdll is the system call contract, but in practice you call the subsystem specific API, typically the Win32 API, which is huge compared to the Linux syscall list because it includes all sorts of things like UI, COM (!), etc.

The project has some of the properties discussed above such as not having a typical main() (or winmain), because there’s no CRT to call it.

Dwedit•4h ago
Pretty much yeah.

You have your usual Win32 API functions found in libraries like Kernel32, User32, and GDI32, but since after Windows XP, those don't actually make system calls. The actual system calls are found in NTDLL and Win32U. Lots of functions you can import, and they're basically one instruction long. Just SYSENTER for the native version, or a switch back to 64-bit mode for a WOW64 DLL. The names of the function always begin with Nt, like NtCreateFile. There's a corresponding Kernel mode call that starts with Zw instead, so in Kernel mode you have ZwCreateFile.

But the system call numbers used with SYSENTER are indeed reordered every time there's a major version change to Windows, so you just call into NTDLL or Win32U instead if you want to directly make a system call.

antihero•5h ago
> Windows support is a requirement

Why, exactly?

AnimalMuppet•5h ago
> Windows support is a requirement...

For what?

There is some software for which Windows support is required. There are others for which it is not, and never will be. (And for an article about running ELF files on RiscV with a Linux OS, the "Windows support" complaint seems a bit odd...)

throwawaysoxjje•5h ago
A requirement from whom? To do what?
rfl890•4h ago
You can make CRT-free Win32 programs, read this guide[1] and you're all set. I've written a couple CLI utilities which are completely CRT-free and weigh just under a few kilobytes.

[1]: https://nullprogram.com/blog/2023/02/15/

forrestthewoods•4h ago
Great post!
WJW•4h ago
Obviously only a requirement if you intend your software to run under windows. But if you don't, why bother. Not all software is intended to be distributed to users far and wide. Some of it is just for yourself, and some of it will only ever run on linux servers.
forrestthewoods•4h ago
> some of it will only ever run on linux servers.

I’ve spent quite a lot of time dealing with code that will ever run on Linux which did not in fact only ever run on Linux!

Obviously for hobby projects anyone can do what they want. But adult projects should support Windows imho and consider Windows support from the start. Cross-platform is super easy unless you choose to make it hard.

WJW•3h ago
I don't think we are talking about the same type of software? The type I was talking about will only ever run on Linux because it's a (HTTP-ish) server that will only ever run on Linux.

Probably a server that is only ever run by a single company on a single CPU type. That company will have complete control of the OS stack, so if it says no Windows, then no Windows has to be supported.

jjmarr•5h ago
Tons of driver code does this.
1718627440•5h ago
I generally try to stay portable, but file descriptors are just to nice, to not use them.
Retr0id•4h ago
File descriptors are part of the linux syscall API, not libc. Are you thinking of FILE?
1718627440•3h ago
I did mean file descriptors.
Retr0id•2h ago
Then I'm confused by what you meant, because you can use fds with or without libc.
ajross•2h ago
The "syscall API" is part of libc too. The read syscall is a trap, you put arguments in the right registers and issue the correct instruction[1] to enter the kernel. That's not something that can be expressed in C. The read() function that your C code actually uses is a C function provided by the C library.

[1] "svc 0" on ARM, "int 0x80" on i386, etc...

Retr0id•2h ago
syscalls are an implementation detail of some libc impls on some platforms, but the C spec does not mention syscalls.
electroly•5h ago
Not exactly the same, but on Windows if you use entirely Win32 calls you can avoid linking any C runtime library. Win32 is below the C standard library on Windows and the C runtime is optional.
okanat•3h ago
This is one of the cornerstones that guarantee Windows can easily upgrade the C runtime and make performance and security upgrades. Win32 APIs have a different function calling ABI too.

So only part of that gets "bloated" is Win32 API itself (which is spread across multiple DLLs and don't actually bloat RAM usage). Most of the time even those functions and structures are carefully designed to have some future-proofness but it is usual to see APIs like CreateFile, CreateFile2, CreateFile3. Internally the earlier versions are upgraded to call the latest version. So not so much bloating there either.

When the C runtime and the OS system calls are combined into the single binary like POSIX, it creates the ABI hell we're in with the modern Unix-likes. Either the OSes have to regularly break the C ABI compatibility for the updates or we have to live with terrible implementations.

GNU libc and Linux combo is particularly bad. On GNU/Linux (or any other current libc replacements), the dynamic loading is also provided by the C library. This makes "forever" binary file compatibility particularly tricky to achieve. Glibc broke certain games / Steam by removing some parts of their ELF implementation: https://sourceware.org/bugzilla/show_bug.cgi?id=32653 . They backed due to huge backlash from the community.

If "the year of Linux desktop" would ever happen, they need to either do an Android and change the definition of what a software package is, or split Glibc into 3 parts: syscalls, dynamic loader and the actual C library.

PS: There is actually a catch to your " C runtime is optional." argument. Microsoft still intentionally holds back the ability of compiling native ABI Windows programs without Visual Studio.

The structured exception handlers (equivalent of Windows for SIGILL, SIGBUS etc.. not for SIGINT or SIGTERM though) are populated by the object files from the C runtime libraries (called VCRuntime/VCStartup). So it is actually not possible to have official Windows binaries without MSVC or any other C runtime like Mingw-64 that provides those symbols. It looks like some developers in Microsoft wanted to open-source VCRuntime / VCStartup but it was ~vetoed~ not fully approved by some people: https://github.com/microsoft/STL/issues/4560#issuecomment-23... , https://www.reddit.com/r/cpp/comments/1l8mqlv/is_msvc_ever_g...

1718627440•2h ago
> split Glibc into 3 parts: syscalls, dynamic loader and the actual C library.

What is left of the C standard library, if you remove syscall wrappers?

> ABI hell

Is that really the case? From my understanding the problem is more, that Linux isn't an OS, so you can't rely on any *.so being there.

okanat•2h ago
> > split Glibc into 3 parts: syscalls, dynamic loader and the actual C library.

> What is left of the C standard library, if you remove syscall wrappers?

Still quite a bit actually. Stuff like malloc, realloc, free, fopen, FILE, getaddrinfo, getlogin, math functions like cos, sin tan, stdatomic implementations, some string functions are all defined in C library. They are not direct system calls unlike: open, read, write, ioctl, setsockopt, capget, capset ....

> > ABI hell

> Is that really the case? From my understanding the problem is more, that Linux isn't an OS, so you can't rely on any *.so being there.

That's why I used more specific term GNU/Linux at the start. There is no guarantee of any .so file can be successfully loaded even if it is there. Glibc can break anything. With the Steam bug I linked this is exactly what happened. Shared object files were there, Glibc stopped supporting a certain ELF file field.

There is only and only one guarantee with Linux-based systems: syscalls (and other similar ways to talk with kernel like ioctl struct memory layouts etc) always keep working.

There is so much invisible dependence on Glibc behavior. Glibc also controls how the DNS works for the programs for example. That also needs to be split into a different library. Same for managing user info like `getlogin`. Moreover all this functionality is actually implemented as dynamic library plugins in Glibc (NSSwitch) that rely on ld.so that's also shipped by Glibc. It is literally a Medusa head of snakes that bite multiple tails. It is extremely hard to test ABI breakages like this.

1718627440•1h ago
> malloc, realloc, free

Wrapper around sbrk, mmap, etc. whatever the modern variant is.

> fopen, FILE

Wrapper around open, write, read, close.

> stdatomic implementations

You can argue, these are wrappers around thread syscalls.

> math functions like cos, sin tan, some string functions are all defined in C library

True for these, but they are so small, they could just be inlined directly, on their own they wouldn't necessarily deserve a library.

> That's why I used more specific term GNU/Linux at the start.

While GNU/Linux does describe a complete OS, it doesn't describe any specific OS. Every Distro does it's own thing, so I think these is what you actually need to call an OS. But everything is built so that the user can take the control over the architecture and which components the OS consists of, so every installation can be a snowflake, and then it is technically its own OS.

I personally consider libc and the compiler (which both make a C implementation) to be part of the OS. I think this is both grounded in theory and in practice. Only in some weird middle ground between theory and practice you can consider them to not be.

mmsc•6h ago
It's also possible to pack a whole codebase into "before main()" - or with no main() at all. I was recently experimenting doing this, as well as a whole codebase that only uses main() and calls itself over and over. Good fun: https://joshua.hu/packing-codebase-into-single-function-disr...
1718627440•3h ago
That is a really fun read and honestly doesn't even seem to be complicated and brittle. Just rename every function to main(100+n, ...).
khaledh•5h ago
> A note on interpreters: If the executable file starts with a shebang (#!), the kernel will use the shebang-specified interpreter to run the program. For example, #!/usr/bin/python3 will run the program using the Python interpreter, #!/bin/bash will run the program using the Bash shell, etc.

This caused me a lot of pain while trying to debug a 3rd party Java application that was trying to launch an executable script, and throwing an IO error "java.io.IOException: error=2, No such file or directory." I was puzzled because I know the script is right there (using its full path) and it had the executable bit set. It turns out that the shebang in the script was wrong, so the OS was complaining (actual error from a shell would be "The file specified the interpreter '/foo/bar', which is not an executable command."), but the Java error was completely misleading :|

Note: If you wonder why I didn't see this error by running the script myself: I did, and it ran fine locally. But the application was running on a remote host that had a different path for the interpreter.

mscdex•5h ago
Also be aware that kernel support for shebangs depends on CONFIG_BINFMT_SCRIPT=y being in the kernel config.
1718627440•5h ago
Note, that this is not a Java specific problem, it can occur with other programs as well. "No such file or directory" is just the nice description for ENOENT, which can occur in a lot of syscalls. I typically just run the program through strace, then you will quickly see what the program did.
gjf•5h ago
For those interested, I did a breakdown of the hashbang: https://blog.foletta.net/post/2021-04-19-what-the/
itopaloglu83•5h ago
I like doing this with old microcontrollers like PIC16 series etc. You said see how to stack pointer, timers, and variables etc. all are configured.
fweimer•4h ago
> The ELF file contains a dynamic section which tells the kernel which shared libraries to load, and another section which tells the kernel to dynamically “relocate” pointers to those functions, so everything checks out.

This is not how dynamic linking works on GNU/Linux. The kernel processes the program headers for the main program (mapping the PT_LOAD segments, without relocating them) and notices the PT_INTERP program interpreter (the path to the dynamic linker) among the program headers. The kernel then loads the dynamic linker in much the same way as the main program (again without relocation) and transfers control to its entry point. It's up to the dynamic linker to self-relocate, load the referenced share objects (this time using plain mmap and mprotect, the kernel ELF loader is not used for that), relocate them and the main program, and then transfer control to the main program.

The scheme is not that dissimilar to the #! shebang lines, with the dynamic linker taking the role of the script interpreter, except that ELF is a binary format.

amitprasad•4h ago
You’re right, and I knew this back in February when I wrote most of this post. I must have revised it down incorrectly before posting; will correct. Bit of a facepalm from my side.
mkoubaa•2h ago
I've always wondered why there weren't more popular loaders to choose from given that on Linux loaders are user-space
BobbyTables2•1h ago
I suspect it is because they get really hairy.

Loading ELFs and processing relocations is actually not too bad. It’s fun after the initial learning curve.

Then one has to worry about handling of “dlopen” and the loader creating the data structures it cares about. Yuck!!!

It’s kinda a shame because the glibc loader is a bit bloated with all the audit and preload handling. Great for flexibility, not for security.

ksherlock•34m ago
There's also binfmt support, which can check a supposedly executable file against some magic and auto-launch an interpreter (like wine or java or dosemu). I looked into it for something once but in my case the magic wasn't good enough.

https://www.kernel.org/doc/html/latest/admin-guide/binfmt-mi...

turbert•4h ago
Its been a while since I've touched this stuff but my recollection is the ELF interpreter (ldso, not the kernel) is responsible for everything after mapping the initial ELF's segments.

iirc execve maps pt_load segments from the program header, populates the aux vector on the stack, and jump straight to the ELF interpreter's entry point. Any linked objects are loaded in userspace by the elf interpreter. The kernel has no knowledge of the PLT/GOT.

archmaster•4h ago
This is awesome! To anyone interested in learning more about this, I wrote https://cpu.land/ a couple years ago. It doesn't go as in-depth into e.g. memory layout as OP does but does cover multitasking and how the code is loaded in the first place.
fuzzy_biscuit•1h ago
I love cpu.land! Thanks for creating such a fun resource.
bignerd_95•3h ago
As someone who teaches this stuff at university, I see students getting confused every single year by how textbooks draw memory. The problem is mostly visual, not conceptual.

Most diagrams in books and slides use an old hardware-centric convention: they draw higher addresses at the top of the page and lower addresses at the bottom. People sometimes justify this with an analogy like “floors in a building go up,” so address 0x7fffffffe000 is drawn “higher” than 0x400000.

But this is backwards from how humans read almost everything today. When you look at code in VS Code or any other IDE, line 1 is at the top, then line 2 is below it, then 3, 4, etc. Numbers go up as you go down. Your brain learns: “down = bigger index.”

Memory in a real Linux process actually matches the VS Code model much more closely than the textbook diagrams suggest.

You can see it yourself with:

cat /proc/$$/maps

(pick any PID instead of $$).

    ...
[0x00000000] lower addresses

    ...
[0x00620000] HEAP start

[0x00643000] HEAP extended ↓ (more allocations => higher addresses)

    ...
[0x7ffd8c3f7000] STACK top (<- stack pointer)

                  ↑ the stack pointer starts here and moves upward

                  (toward lower addresses) when you push
[0x7ffd8c418000] STACK start

    ...
[0xffffffffff600000] higher addresses

    ...


The output is printed from low addresses to high addresses. At the top of the output you'll usually see the binary, shared libs, heap, etc. Those all live at lower virtual addresses. Farther down in the output you'll eventually see the stack, which lives at a higher virtual address. In other words: as you scroll down, the addresses get bigger. Exactly like scrolling down in an editor gives you bigger line numbers.

The phrases “the heap grows up” and “the stack grows down” aren't wrong. They're just describing what happens to the numeric addresses: the heap expands toward higher addresses, and the stack moves into lower addresses.

The real problem is how we draw it. We label “up” on the page as “higher address,” which is the opposite of how people read code or even how /proc/<pid>/maps is printed. So students have to mentally flip the diagram before they can even think about what the stack and heap are doing.

If we just drew memory like an editor (low addresses at the top, high addresses further down) it would click instantly. Scroll down, addresses go up, and the stack sits at the bottom. At that point it’s no longer “the stack grows down”: it’s just the stack pointer being decremented, moving to lower addresses (which, in the diagram, means moving upward).

1718627440•2h ago
That's how stacks on my desk grow and how everything grows in reality. I wouldn't numerate stacked things on my desk from the top, since this constantly changes. You also wouldn't name the first branch of a tree (the plant) to be the top-most one.

In your example "the stack grows down", seems to be wrong in the image.

bignerd_95•2h ago
Thanks! I tried to rewrite the final sentence
1718627440•2h ago
Yeah, but does that really help? The phrases "growing down/up" still exist and now you defined them to mean the opposite. This issue still didn't go away, since heap and stack still grow in different directions. Can't you just start drawing from the bottom of the blackboard, and it will be obvious? Coordinate systems also typically work that way.
ofalkaed•2h ago
Starting at the bottom of the blackboard would be backwards from how it prints in the terminal when you cat /proc/<pid>/maps.
bignerd_95•1h ago
Yes, I draw the heap starting at the top of the board and the stack starting at the bottom of the board and grow them toward each other. That works fine in a one-off explanation.

The problem is that most textbooks draw the opposite, so the student leaves my lecture, opens a book or a slide deck, and now “down” means a different thing.

It gets worse when they get curious and look at a real process with /proc/<pid>/maps. Linux prints mappings from low address to high address as you scroll down (which matches my representation). That is literally reversed from the usual textbook diagram. Students notice and ask why the book is “wrong.”

So I've learned I have to explicitly call this out as notation.

Same story as in electronics class still teaching conventional current flow (positive to negative), even though electrons move the other way (negative to positive). Source: https://www.allaboutcircuits.com/textbook/direct-current/chp.... Historical convention, and then pedagogy has to patch it forever.

amitprasad•2h ago
I think I got stuck in the same rut that I learned address space in whilst writing that diagram. I would tend to agree with you that your model makes much more sense to the student.

Related: In notation, one thing that I used to struggle with is how addresses (e.g. 0xAB_CD) actually have the bit representation of [0xCD, 0xAB]. Wonder if there's a common way to address that?

bignerd_95•1h ago
Yes, I reached the same conclusions the hard way while exploiting memory corruption bugs. Once I understood how misleading these representations can be, everything finally became clear.

About the address notation you're describing, I'm not sure I fully get the problem. Can you spell out the question with a concrete example?

This is what the address space of a real bash process looks like on my machine:

__

$ cat /proc/$(pidof bash)/maps

5e6e8fd0f000-5e6e8fd3f000 r--p 00000000 fc:00 3539412 /usr/bin/bash

5e6e8fd3f000-5e6e8fe2e000 r-xp 00030000 fc:00 3539412 /usr/bin/bash

5e6e8fe2e000-5e6e8fe63000 r--p 0011f000 fc:00 3539412 /usr/bin/bash

5e6e8fe63000-5e6e8fe67000 r--p 00154000 fc:00 3539412 /usr/bin/bash

5e6e8fe67000-5e6e8fe70000 rw-p 00158000 fc:00 3539412 /usr/bin/bash

5e6e8fe70000-5e6e8fe7b000 rw-p 00000000 00:00 0

5e6e94891000-5e6e94a1e000 rw-p 00000000 00:00 0 [heap]

7ec3d1400000-7ec3d16eb000 r--p 00000000 fc:00 3550901 /usr/lib/locale/locale-archive

7ec3d1800000-7ec3d1828000 r--p 00000000 fc:00 3548995 /usr/lib/x86_64-linux-gnu/libc.so.6

7ec3d1828000-7ec3d19b0000 r-xp 00028000 fc:00 3548995 /usr/lib/x86_64-linux-gnu/libc.so.6

7ec3d19b0000-7ec3d19ff000 r--p 001b0000 fc:00 3548995 /usr/lib/x86_64-linux-gnu/libc.so.6

7ec3d19ff000-7ec3d1a03000 r--p 001fe000 fc:00 3548995 /usr/lib/x86_64-linux-gnu/libc.so.6

7ec3d1a03000-7ec3d1a05000 rw-p 00202000 fc:00 3548995 /usr/lib/x86_64-linux-gnu/libc.so.6

7ec3d1a05000-7ec3d1a12000 rw-p 00000000 00:00 0

7ec3d1a2b000-7ec3d1a84000 r--p 00000000 fc:00 3549063 /usr/lib/locale/C.utf8/LC_CTYPE

7ec3d1a84000-7ec3d1a85000 r--p 00000000 fc:00 3549069 /usr/lib/locale/C.utf8/LC_NUMERIC

7ec3d1a85000-7ec3d1a86000 r--p 00000000 fc:00 3549072 /usr/lib/locale/C.utf8/LC_TIME

7ec3d1a86000-7ec3d1a87000 r--p 00000000 fc:00 3549062 /usr/lib/locale/C.utf8/LC_COLLATE

7ec3d1a87000-7ec3d1a88000 r--p 00000000 fc:00 3549067 /usr/lib/locale/C.utf8/LC_MONETARY

7ec3d1a88000-7ec3d1a89000 r--p 00000000 fc:00 3549066 /usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES

7ec3d1a89000-7ec3d1a8a000 r--p 00000000 fc:00 3549070 /usr/lib/locale/C.utf8/LC_PAPER

7ec3d1a8a000-7ec3d1a8b000 r--p 00000000 fc:00 3549068 /usr/lib/locale/C.utf8/LC_NAME

7ec3d1a8b000-7ec3d1a8c000 r--p 00000000 fc:00 3549061 /usr/lib/locale/C.utf8/LC_ADDRESS

7ec3d1a8c000-7ec3d1a8d000 r--p 00000000 fc:00 3549071 /usr/lib/locale/C.utf8/LC_TELEPHONE

7ec3d1a8d000-7ec3d1a90000 rw-p 00000000 00:00 0

7ec3d1a90000-7ec3d1a9e000 r--p 00000000 fc:00 3551411 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.4

7ec3d1a9e000-7ec3d1ab1000 r-xp 0000e000 fc:00 3551411 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.4

7ec3d1ab1000-7ec3d1abf000 r--p 00021000 fc:00 3551411 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.4

7ec3d1abf000-7ec3d1ac3000 r--p 0002e000 fc:00 3551411 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.4

7ec3d1ac3000-7ec3d1ac4000 rw-p 00032000 fc:00 3551411 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.4

7ec3d1ac4000-7ec3d1ac5000 r--p 00000000 fc:00 3549065 /usr/lib/locale/C.utf8/LC_MEASUREMENT

7ec3d1ac5000-7ec3d1ac6000 r--p 00000000 fc:00 3549064 /usr/lib/locale/C.utf8/LC_IDENTIFICATION

7ec3d1ac6000-7ec3d1acd000 r--s 00000000 fc:00 3548984 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache

7ec3d1acd000-7ec3d1acf000 rw-p 00000000 00:00 0

7ec3d1acf000-7ec3d1ad0000 r--p 00000000 fc:00 3548992 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

7ec3d1ad0000-7ec3d1afb000 r-xp 00001000 fc:00 3548992 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

7ec3d1afb000-7ec3d1b05000 r--p 0002c000 fc:00 3548992 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

7ec3d1b05000-7ec3d1b07000 r--p 00036000 fc:00 3548992 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

7ec3d1b07000-7ec3d1b09000 rw-p 00038000 fc:00 3548992 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

7ffd266f8000-7ffd26719000 rw-p 00000000 00:00 0 [stack]

7ffd2678a000-7ffd2678e000 r--p 00000000 00:00 0 [vvar]

7ffd2678e000-7ffd26790000 r-xp 00000000 00:00 0 [vdso]

ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]

___

Each line is a memory mapping. The first field is the start address. The second field is the end address. So an entry like

7ffd266f8000-7ffd26719000

means "this mapping covers virtual addresses from 0x7ffd266f8000 up to 0x7ffd26719000."

The addresses are always increasing:

- left to right: within a single line you go from lower address to higher address

- top to bottom: as you go down the list you also go to higher and higher addresses

Exactly like reading a book: left to right and then top to bottom.

1718627440•1h ago
The issue amitprasad is pointing out is when you read addresses byte-wise and you determine that they are in little-endian.
bignerd_95•59m ago
If you're referring to little-endianness, it means the CPU stores multi-byte values in memory with the least significant byte first (at the lowest address).

This convention started on early Intel chips and was kept for backward compatibility. It also has a practical benefit: it makes basic arithmetic and type widening cheaper in hardware. The "low" part of the value is always at the base address, so the CPU can load 8 bits, then 16 bits, then 32 bits, etc. starting from the same address without extra offset math.

So when you say an address like 0xABCD shows up in memory as [0xCD, 0xAB] byte-by-byte, that's not the address being "reversed". That's just the little-endian in-memory layout of that numeric value.

There are also big-endian architectures, where the most significant byte is stored at the lowest address. That matches how humans usually write numbers (0xABCD in memory as [0xAB, 0xCD]). But most mainstream desktop/server CPUs today are little-endian, so you mostly see the little-endian view.

amitprasad•58m ago
Not so much the confusion of what little endian is, but how we tend to represent it in notation. Of course this confusion was back when I was first learning things in high school, but I imagine I’m not alone in it
ramanvarma•2h ago
did you see the relocations for the main binary applied before or after the linker resolves its own symbols? the ordering always feels like black magic when you step through it in a debugger