From ba7d38240198ba854384328843da52a26209f488 Mon Sep 17 00:00:00 2001
From: johannst zsh(1)
Keybindings
@@ -1886,6 +1887,45 @@ launched with the same parameters.
pacman -Sy refresh package database
+pacman -S <pkg> install pkg
+pacman -Ss <regex> search remote package database
+pacman -Si <pkg> get info for pkg
+pacman -Su upgrade installed packages
+pacman -Sc clean local package cache
+
+pacman -Rsn <pkg> uninstall package and unneeded deps + config files
+
+Local package database of installed packages.
+pacman -Q list all installed packages
+pacman -Qs <regex> search local package database
+pacman -Ql <pkg> list files installed by pkg
+pacman -Qo <file> query package that owns file
+pacman -Qe only list explicitly installed packages
+
+Local file database which allows to search packages owning certain files. +Also searches non installed packages, but database must be synced.
+pacman -Fy refresh file database
+pacman -Fl <pkg> list files in pkg (must not be installed)
+pacman -Fx <regex> search
+
+Uninstall all orphaned packages (including config files) that were installed as +dependencies.
+pacman -Rsn $(pacman -Qqtq)
+
+List explicitly installed packages that are not required as dependency by any +package and sort by size.
+pacman -Qetq | xargs pacman -Qi |
+ awk '/Name/ { name=$3 }
+ /Installed Size/ { printf "%8.2f%s %s\n", $4, $5, name }' |
+ sort -h
+
.rodata
section as follows:
-E
run only preprocessor-dM
list only #define
statements# List all target options with their description.
+gcc --help=target
+
+# Configure for current cpu arch and query (-Q) value of options.
+gcc -march=native -Q --help=target
+
__builtin_expect(expr, cond)
Give the compiler a hint which branch is hot, so it can lay out the code
@@ -2546,6 +2595,303 @@ search for and where to put the function pointer:
As we can see the offset from relocation at index 0
points to GOT[3]
.
+
The ELF symbol versioning mechanism allows to attach version +information to symbols. +This can be used to express symbol version requirements or to provide certain +symbols multiple times in the same ELF file with different versions (eg for +backwards compatibility).
+The libpthread.so
library is an example which provides the
+pthread_cond_wait
symbol multiple times but in different versions.
+With readelf the version of the symbol can be seen after the @
.
> readelf -W --dyn-syms /lib/libpthread.so
+
+Symbol table '.dynsym' contains 342 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ ...
+ 141: 0000f080 696 FUNC GLOBAL DEFAULT 16 pthread_cond_wait@@GLIBC_2.3.2
+ 142: 00010000 111 FUNC GLOBAL DEFAULT 16 pthread_cond_wait@GLIBC_2.2.5
+
+The @@
denotes the default symbol version which will be used during
+static linking against the library.
+The following dump shows that the tmp
program linked against lpthread
will
+depend on the symbol version GLIBC_2.3.2
, which is the default version.
> echo "#include <pthread.h>
+ int main() {
+ return pthread_cond_wait(0,0);
+ }" | gcc -o tmp -xc - -lpthread;
+ readelf -W --dyn-syms tmp | grep pthread_cond_wait;
+
+Symbol table '.dynsym' contains 7 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ ...
+ 2: 00000000 0 FUNC GLOBAL DEFAULT UND pthread_cond_wait@GLIBC_2.3.2 (2)
+
+++Only one symbol can be annotated as the
+@@
default version.
Using the --version-info
flag with readelf, more details on the symbol
+version info compiled into the tmp
ELF file can be obtained.
.gnu.version
section contains the version definition for each symbol in
+the .dynsym
section. pthread_cond_wait
is at index 2
in the .dynsym
+section, the corresponding symbol version is at index 2
in the
+.gnu.version
section..gnu.version_r
section contains symbol version requirements per shared
+library dependency (DT_NEEDED
dynamic entry).> readelf -W --version-info --dyn-syms tmp
+
+Symbol table '.dynsym' contains 7 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+ 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
+ 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND pthread_cond_wait@GLIBC_2.3.2 (2)
+ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3)
+ 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
+ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
+ 6: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (3)
+
+Version symbols section '.gnu.version' contains 7 entries:
+ Addr: 0x0000000000000534 Offset: 0x000534 Link: 6 (.dynsym)
+ 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.3.2) 3 (GLIBC_2.2.5)
+ 004: 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5)
+
+Version needs section '.gnu.version_r' contains 2 entries:
+ Addr: 0x0000000000000548 Offset: 0x000548 Link: 7 (.dynstr)
+ 000000: Version: 1 File: libc.so.6 Cnt: 1
+ 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3
+ 0x0020: Version: 1 File: libpthread.so.0 Cnt: 1
+ 0x0030: Name: GLIBC_2.3.2 Flags: none Version: 2
+
+The gnu dynamic linker allows to inspect the version processing during runtime
+by setting the LD_DEBUG
environment variable accordingly.
# version: Display version dependencies.
+> LD_DEBUG=versions ./tmp
+ 717904: checking for version `GLIBC_2.2.5' in file /usr/lib/libc.so.6 [0] required by file ./tmp [0]
+ 717904: checking for version `GLIBC_2.3.2' in file /usr/lib/libpthread.so.0 [0] required by file ./tmp [0]
+ ...
+
+# symbols : Display symbol table processing.
+# bindings: Display information about symbol binding.
+> LD_DEBUG=symbols,bindings ./tmp
+ ...
+ 718123: symbol=pthread_cond_wait; lookup in file=./tmp [0]
+ 718123: symbol=pthread_cond_wait; lookup in file=/usr/lib/libpthread.so.0 [0]
+ 718123: binding file ./tmp [0] to /usr/lib/libpthread.so.0 [0]: normal symbol `pthread_cond_wait' [GLIBC_2.3.2]
+
+The following shows an example C++ library libfoo
which provides the same
+symbol multiple times but in different versions.
// file: libfoo.cc
+#include<stdio.h>
+
+// Bind function symbols to version nodes.
+//
+// ..@ -> Is the unversioned symbol.
+// ..@@.. -> Is the default symbol.
+
+__asm__(".symver func_v0,func@");
+__asm__(".symver func_v1,func@LIB_V1");
+__asm__(".symver func_v2,func@@LIB_V2");
+
+extern "C" {
+ void func_v0() { puts("func_v0"); }
+ void func_v1() { puts("func_v1"); }
+ void func_v2() { puts("func_v2"); }
+}
+
+__asm__(".symver _Z11func_cpp_v1i,_Z8func_cppi@LIB_V1");
+__asm__(".symver _Z11func_cpp_v2i,_Z8func_cppi@@LIB_V2");
+
+void func_cpp_v1(int) { puts("func_cpp_v1"); }
+void func_cpp_v2(int) { puts("func_cpp_v2"); }
+
+void func_cpp(int) { puts("func_cpp_v2"); }
+
+Version script for libfoo
which defines which symbols for which versions are
+exported from the ELF file.
# file: libfoo.ver
+LIB_V1 {
+ global:
+ func;
+ extern "C++" {
+ "func_cpp(int)";
+ };
+ local:
+ *;
+};
+
+LIB_V2 {
+ global:
+ func;
+ extern "C++" {
+ "func_cpp(int)";
+ };
+} LIB_V1;
+
+++The local: section in
+LIB_V1
is a catch all, that matches any symbol +not explicitly specified, and defines that the symbol is local and therefore +not exported from the ELF file.
The library libfoo
can be linked with the version definitions in libfoo.ver
+by passing the version script to the linker with the --version-script
flag.
> g++ -shared -fPIC -o libfoo.so libfoo.cc -Wl,--version-script=libfoo.ver
+> readelf -W --dyn-syms libfoo.so | c++filt
+
+Symbol table '.dynsym' contains 14 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ ...
+ 6: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LIB_V1
+ 7: 000000000000114b 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@LIB_V1
+ 8: 0000000000001168 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@@LIB_V2
+ 9: 0000000000001185 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@@LIB_V1
+ 10: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LIB_V2
+ 11: 0000000000001109 22 FUNC GLOBAL DEFAULT 13 func
+ 12: 000000000000111f 22 FUNC GLOBAL DEFAULT 13 func@LIB_V1
+ 13: 0000000000001135 22 FUNC GLOBAL DEFAULT 13 func@@LIB_V2
+
+The following program demonstrates how to make use of the different versions:
+// file: main.cc
+#include <dlfcn.h>
+#include <assert.h>
+
+// Links against default symbol in the lib.so.
+extern "C" void func();
+
+int main() {
+ // Call the default version.
+ func();
+
+#ifdef _GNU_SOURCE
+ typedef void (*fnptr)();
+
+ // Unversioned lookup.
+ fnptr fn_v0 = (fnptr)dlsym(RTLD_DEFAULT, "func");
+ // Version lookup.
+ fnptr fn_v1 = (fnptr)dlvsym(RTLD_DEFAULT, "func", "LIB_V1");
+ fnptr fn_v2 = (fnptr)dlvsym(RTLD_DEFAULT, "func", "LIB_V2");
+
+ assert(fn_v0 != 0);
+ assert(fn_v1 != 0);
+ assert(fn_v2 != 0);
+
+ fn_v0();
+ fn_v1();
+ fn_v2();
+#endif
+
+ return 0;
+}
+
+Compiling and running results in:
+> g++ -o main main.cc -ldl ./libfoo.so && ./main
+func_v2
+func_v0
+func_v1
+func_v2
+
+Some decorator examples with type annotation.
+from typing import Callable
+
+def log(f: Callable[[int], None]) -> Callable[[int], None]:
+ def inner(x: int):
+ print(f"log::inner f={f.__name__} x={x}")
+ f(x)
+ return inner
+
+@log
+def some_fn(x: int):
+ print(f"some_fn x={x}")
+
+
+def log_tag(tag: str) -> Callable[[Callable[[int], None]], Callable[[int], None]]:
+ def decorator(f: Callable[[int], None]) -> Callable[[int], None]:
+ def inner(x: int):
+ print(f"log_tag::inner f={f.__name__} tag={tag} x={x}")
+ f(x)
+ return inner
+ return decorator
+
+@log_tag("some_tag")
+def some_fn2(x: int):
+ print(f"some_fn2 x={x}")
+
+Walrus operator :=
added since python 3.8.
from typing import Optional
+
+# Example 1: if let statements
+
+def foo(ret: Optional[int]) -> Optional[int]:
+ return ret
+
+if r := foo(None):
+ print(f"foo(None) -> {r}")
+
+if r := foo(1337):
+ print(f"foo(1337) -> {r}")
+
+# Example 2: while let statements
+
+toks = iter(['a', 'b', 'c'])
+while tok := next(toks, None):
+ print(f"{tok}")
+
+# Example 3: list comprehension
+
+print([tok for t in [" a", " ", " b "] if (tok := t.strip())])
+
+Run unittests directly from the command line as
+python3 -m unittest -v test
Optionally pass -k <patter>
to only run subset of tests.
# file: test.py
+
+import unittest
+
+class MyTest(unittest.TestCase):
+ def setUp(self):
+ pass
+ def tearDown(self):
+ pass
+ # Tests need to start with the prefix 'test'.
+ def test_foo(self):
+ self.assertEqual(1 + 2, 3)
+ def test_bar(self):
+ with self.assertRaises(IndexError):
+ list()[0]
+
+Run doctests directly from the command line as
+python -m doctest -v test.py
# file: test.py
+
+def sum(a: int, b: int) -> int:
+ """Sum a and b.
+
+ >>> sum(1, 2)
+ 3
+
+ >>> sum(10, 20)
+ 30
+ """
+ return a + b
+
+Micro benchmarking.
+python -m timeit '[x.strip() for x in ["a ", " b"]]'
+
> gcc -o greet greet.s -nostartfiles -nostdlib && ./greet
Hi ASM-World!
-Different addressing modes.
-str r1, [r0] // [r0]=r1
-str r1, [r0, #4] // [r0+4]=r1
-str r1, [r0, #4]! // r0+=4; [r0]=r1
-str r1, [r0], 4 // [r0]=r1; r0+=4
+ldr r1, [r0] // r1 = [r0]
+ldr r1, [r0, #4] // r1 = [r0+4]
+
+ldr r1, [r0, #4]! // pre-inc : r0+=4; r1 = [r0]
+ldr r1, [r0], #4 // post-inc: [r0] = r1; r0+=4
+
+ldr r0, [r1, r2, lsl #3] // r0 = [r1 + (r2<<3)]
Load/store multiple registers full-descending.
stmfd r0!, {r1-r2, r5} // r0-=4; [r0]=r5
@@ -3275,7 +3624,7 @@ Hi ASM-World!
distributions. Explicitly specifying the dynamic linker should not be
required when compiling natively on arm.
-References
+References
- Procedure Call Standard ARM
- ARMv7-A Programmer's Guide
--
cgit v1.2.3