LIBUNWIND-IA64(3libunwind)

๐Ÿ“ฆ
version 1.8.3 ยท 3 versions
, in alpine 3.24, arch rolling, epel 10, epel 9, fedora 43, fedora 44, nixpkgs unstable

๐Ÿ’– libunwind-ia64 โ€” IA-64-specific support in libunwind ๐Ÿ’–

okay bestie, welcome to the 3libunwind manual, the IA-64 edition โœจ this whole page lives in the Programming Library section, and it's all about the Itanium-flavored corner of libunwind. let's get into it ๐Ÿฆ‹


๐ŸŒธ NAME ๐ŸŒธ

libunwind-ia64 โ€” IA-64-specific support in libunwind


โœจ INTRODUCTION โœจ

so the IA-64 version of libunwind? it rolls with a platform-string of ia64 and โ€” at least in theory ๐Ÿ‘€ โ€” should be able to support all operating systems that adhere to the processor-specific ABI defined for the Itanium Processor Family. that includes both little-endian Linux and big-endian HP-UX, iconic range honestly ๐ŸŒˆ

and to make it possible for a single library to unwind both 32- and 64-bit targets, the type unw_word_t is always defined to be 64 bits wide โ€” independent of the natural word-size of the host. slay ๐Ÿ’…

but having said all thatโ€ฆ the current implementation has been tested only with IA-64 Linux. no cap. so keep that in mind fr fr ๐Ÿ˜ญ

when you're targeting IA-64, the libunwind header file defines the macro UNW_TARGET_IA64 as 1 and the macro UNW_TARGET as "ia64" (without the quotation marks, bestie, those are just for show here). the first one lets platform-dependent unwind code use conditional-compilation to pick the appropriate implementation. the second one is useful for stringification purposes and for constructing target-platform-specific symbols. very demure, very mindful ๐ŸŽ€

one special feature of IA-64 is the use of NaT bits to support speculative execution. usually people think of NaT bits as the "65-th bit" of a general register. but to make everything fit into 64-bit wide unw_word_t values, libunwind treats the NaT-bits like separate boolean registers, whose 64-bit value is either TRUE (non-zero) or FALSE (zero). tiny but mighty ๐Ÿ’–


๐Ÿ‘‘ MACHINE-STATE ๐Ÿ‘‘

the machine-state (aka the set of registers) that you can reach through libunwind depends on the type of stack frame that a cursor points to. so:

  • for normal frames, all "preserved" (callee-saved) registers are accessible.
  • for signal-trampoline frames, all registers are accessible โ€” including "scratch" (caller-saved) registers ๐Ÿ”ฅ

most applications do not have to worry a-priori about which registers are accessible when. and if you're ever in doubt, it is always safe to just try to access a register (via unw_get_reg() or unw_get_fpreg()) โ€” and if the register isn't accessible, the call will fail with a return-value of -UNW_EBADREG. no harm, no foul ๐Ÿ’œ

as a special exception to the above general rule, the scratch registers r15-r18 are always accessible, even in normal frames. this makes it possible to pass arguments, e.g., to exception handlers. periodt โœจ

for a detailed description of the IA-64 register usage convention, please see the "Itanium Software Conventions and Runtime Architecture Guide", available at:

http://www.intel.com/design/itanium/downloads/245358.htm

๐Ÿฆ‹ REGISTER NAMES ๐Ÿฆ‹

the IA-64-version of libunwind defines three kinds of register name macros: frame-register macros, normal register macros, and convenience macros. below, we describe each kind in turn ๐Ÿ’ซ

๐ŸŽ€ FRAME-REGISTER MACROS ๐ŸŽ€

frame-registers are special (pseudo) registers because they always have a valid value โ€” even though sometimes they don't get saved explicitly. like, if a memory stack frame is 16 bytes in size, the previous stack-pointer value can be calculated simply as sp+16, so there's no need to save the stack-pointer explicitly. efficiency queen ๐Ÿ‘‘

moreover, the set of frame register values uniquely identifies a stack frame. the IA-64 architecture defines two stacks (a memory and a register stack). including the instruction-pointer (IP), this means there are three frame registers:

  • UNW_IA64_IP โ€” Contains the instruction pointer (IP, or "program counter") of the current stack frame. given this value, the remaining machine-state corresponds to the register-values that were present in the CPU when it was just about to execute the instruction pointed to by UNW_IA64_IP. bits 0 and 1 of this frame-register encode the slot number of the instruction. Note: due to the way the call instruction works on IA-64, the slot number is usually zero, but can be non-zero, e.g., in the stack-frame of a signal-handler trampoline ๐Ÿ‘€
  • UNW_IA64_SP โ€” Contains the (memory) stack-pointer value (SP).
  • UNW_IA64_BSP โ€” Contains the register backing-store pointer (BSP). Note: the value in this register is equal to the contents of register ar.bsp at the time the instruction at UNW_IA64_IP was about to begin execution.

๐ŸŒˆ NORMAL REGISTER MACROS ๐ŸŒˆ

the following normal register name macros are available:

  • UNW_IA64_GR โ€” The base-index for general (integer) registers. add an index in the range from 0..127 to get a particular general register. for example, to access r4, the index UNW_IA64_GR+4 should be used. registers r0 and r1 (gp) are read-only, and any attempt to write them will result in an error (-UNW_EREADONLYREG). even though r1 is read-only, libunwind will automatically adjust its value if the instruction-pointer (UNW_IA64_IP) is modified. for example, if UNW_IA64_IP is set to a value inside a function func(), then reading UNW_IA64_GR+1 will return the global-pointer value for this function. she's autonomous ๐Ÿ’…
  • UNW_IA64_NAT โ€” The base-index for the NaT bits of the general (integer) registers. a non-zero value in these registers corresponds to a set NaT-bit. add an index in the range from 0..127 to get a particular NaT-bit register. for example, to access the NaT bit of r4, the index UNW_IA64_NAT+4 should be used.
  • UNW_IA64_FR โ€” The base-index for floating-point registers. add an index in the range from 0..127 to get a particular floating-point register. for example, to access f2, the index UNW_IA64_FR+2 should be used. registers f0 and f1 are read-only, and any attempt to write to indices UNW_IA64_FR+0 or UNW_IA64_FR+1 will result in an error (-UNW_EREADONLYREG).
  • UNW_IA64_AR โ€” The base-index for application registers. add an index in the range from 0..127 to get a particular application register. for example, to access ar40, the index UNW_IA64_AR+40 should be used. the IA-64 architecture defines several application registers as "reserved for future use". attempting to access such registers results in an error (-UNW_EBADREG). not me getting rejected by reserved registers ๐Ÿ˜ญ
  • UNW_IA64_BR โ€” The base-index for branch registers. add an index in the range from 0..7 to get a particular branch register. for example, to access b6, the index UNW_IA64_BR+6 should be used.
  • UNW_IA64_PR โ€” Contains the set of predicate registers. this 64-bit wide register contains registers p0 through p63 in the "broad-side" format. just like with the "move predicates" instruction, the registers are mapped as if CFM.rrb.pr were set to 0. thus, in general the value of predicate register pN with N>=16 can be found in bit 16 + ((N-16)+CFM.rrb.pr) % 48. math girlie behavior ๐Ÿงฎโœจ
  • UNW_IA64_CFM โ€” Contains the current-frame-mask register.

๐Ÿ’œ CONVENIENCE MACROS ๐Ÿ’œ

convenience macros are simply aliases for certain frequently used registers:

  • UNW_IA64_GP โ€” Alias for UNW_IA64_GR+1, the global-pointer register.
  • UNW_IA64_TP โ€” Alias for UNW_IA64_GR+13, the thread-pointer register.
  • UNW_IA64_AR_RSC โ€” Alias for UNW_IA64_GR+16, the register-stack configuration register.
  • UNW_IA64_AR_BSP โ€” Alias for UNW_IA64_GR+17. this register index accesses the value of register ar.bsp as of the time it was last saved explicitly. this is rarely what you want. normally, you'll want to use UNW_IA64_BSP instead. lowkey a trap, bestie ๐Ÿชค
  • UNW_IA64_AR_BSPSTORE โ€” Alias for UNW_IA64_GR+18, the register-backing store write pointer.
  • UNW_IA64_AR_RNAT โ€” Alias for UNW_IA64_GR+19, the register-backing store NaT-collection register.
  • UNW_IA64_AR_CCV โ€” Alias for UNW_IA64_GR+32, the compare-and-swap value register.
  • UNW_IA64_AR_CSD โ€” Alias for UNW_IA64_GR+25, the compare-and-swap-data register (used by 16-byte atomic operations).
  • UNW_IA64_AR_UNAT โ€” Alias for UNW_IA64_GR+36, the user NaT-collection register.
  • UNW_IA64_AR_FPSR โ€” Alias for UNW_IA64_GR+40, the floating-point status (and control) register.
  • UNW_IA64_AR_PFS โ€” Alias for UNW_IA64_GR+64, the previous frame-state register.
  • UNW_IA64_AR_LC โ€” Alias for UNW_IA64_GR+65 the loop-count register.
  • UNW_IA64_AR_EC โ€” Alias for UNW_IA64_GR+66, the epilogue-count register.

๐Ÿซถ THE UNWIND-CONTEXT TYPE ๐Ÿซถ

on IA-64, unw_context_t is simply an alias for ucontext_t (as defined by the Single UNIX Spec). this implies that it's possible to initialize a value of this type not just with unw_getcontext(), but also with getcontext(), for example. very convenient, very iconic โœจ

however โ€” since this is an IA-64-specific extension to libunwind, portable code should not rely on this equivalence. write once, cry once, iykyk ๐Ÿ’€

๐ŸŒŸ SEE ALSO ๐ŸŒŸ


๐Ÿ’– AUTHOR ๐Ÿ’–

David Mosberger-Tang Email: dmosberger@gmail.com WWW: http://www.nongnu.org/libunwind/


and that's the whole page bestie!! this came straight out of the Programming Library manual, dated 29 August 2023 โ€” so if you're out here unwinding on Itanium, you're in the best hands ๐Ÿซถ๐Ÿ’… stay slay, stay 64-bit wide ๐Ÿฆ‹โœจ