summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ogness <john.ogness@linutronix.de>2017-12-19 10:32:14 +0100
committerJohn Ogness <john.ogness@linutronix.de>2017-12-19 10:32:14 +0100
commitbbdbb0189029258a972068661e27df2b1add4519 (patch)
tree2aaa4212df37176ffffc56ae27fdddca1b94d70f
parent67fd50dca5856654f5eb89a7646c4f1184e7d1aa (diff)
embedded devel: add english version
Signed-off-by: John Ogness <john.ogness@linutronix.de>
-rw-r--r--application-devel/embedded-devel/Makefile4
-rw-r--r--application-devel/embedded-devel/pres_embedded-devel_en.tex607
2 files changed, 610 insertions, 1 deletions
diff --git a/application-devel/embedded-devel/Makefile b/application-devel/embedded-devel/Makefile
index ed2e2e7..336a755 100644
--- a/application-devel/embedded-devel/Makefile
+++ b/application-devel/embedded-devel/Makefile
@@ -1 +1,3 @@
-obj-$(CONFIG_DEVEL_EMBEDDED) += hints_embedded-devel_de.pdf pres_embedded-devel_de.pdf
+obj-$(CONFIG_DEVEL_EMBEDDED) += hints_embedded-devel_de.pdf
+obj-$(CONFIG_DEVEL_EMBEDDED) += pres_embedded-devel_de.pdf
+obj-$(CONFIG_DEVEL_EMBEDDED) += pres_embedded-devel_en.pdf
diff --git a/application-devel/embedded-devel/pres_embedded-devel_en.tex b/application-devel/embedded-devel/pres_embedded-devel_en.tex
new file mode 100644
index 0000000..b19afae
--- /dev/null
+++ b/application-devel/embedded-devel/pres_embedded-devel_en.tex
@@ -0,0 +1,607 @@
+\input{configpres}
+
+\title{\lq (Embedded) Linux Application Development\rq}
+\maketitle
+
+\subsection{Toolchains}
+
+\begin{frame}
+\frametitle{What is a toolchain?}
+\pause
+\begin{enumerate}
+\item compiler (gcc)
+\item debugger (gdb)
+\item binutils (as, ld, objdump, ...)
+\item sysroot (ld-linux-x86-64.so.2, libc.so.6, ...)
+\item sysroot-dev (libc.so, stdio.h, ...)
+\end{enumerate}
+\end{frame}
+
+\subsection{The GNU Compiler}
+
+\begin{frame}[fragile]
+\frametitle{Build a Test Program}
+Create a test program: Hello, world!
+\begin{verbatim}
+/* hello.c */
+#include <stdio.h>
+
+int main(void)
+{
+ printf("Hello, world!\n");
+ return 0;
+}
+\end{verbatim}
+Build the test program.
+\begin{verbatim}
+gcc -ohello hello.c
+\end{verbatim}
+\end{frame}
+
+\begin{frame}
+\frametitle{Stages of a Build}
+\begin{enumerate}
+\item pre-processor (evaluate macros)
+\item compiler (convert C code to assembly)
+\item assembler (convert assembly to machine code)
+\item linker (add information for external symbols)
+\end{enumerate}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Stages of a Build}
+pre-process code (evaluate macros)
+\begin{verbatim}
+gcc -E -ohello_pre.c hello.c
+\end{verbatim}
+compile code (C to assembly)
+\begin{verbatim}
+gcc -S -ohello.S hello_pre.c
+\end{verbatim}
+assemble code (assembly to machine)
+\begin{verbatim}
+as -ohello.o hello.S
+\end{verbatim}
+link objects (objects to executable)
+\begin{verbatim}
+ld -I/lib64/ld-linux-x86-64.so.2 -ohello hello.o \
+ /usr/lib/x86_64-linux-gnu/crt[1in].o -lc
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Stages of a Build}
+stop after pre-processor stage
+\begin{verbatim}
+gcc -E hello.c
+\end{verbatim}
+stop after compile stage
+\begin{verbatim}
+gcc -S -ohello.S hello.c
+\end{verbatim}
+stop after assemble stage
+\begin{verbatim}
+gcc -c -ohello.o hello.c
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Important gcc Options}
+compile with optimization level 3
+\begin{verbatim}
+gcc -O3 -ohello hello.c
+\end{verbatim}
+compile without optimization and with debug symbols
+\begin{verbatim}
+gcc -O0 -g -ohello hello.c
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Important gcc Options}
+link against additional libraries (librt)
+\begin{verbatim}
+gcc -ohello hello.c -lrt
+\end{verbatim}
+add extra search paths for libraries
+\begin{verbatim}
+gcc -L/mypath -ohello hello.c -lrt
+\end{verbatim}
+add extra search paths for headers
+\begin{verbatim}
+gcc -I/mypath -ohello hello.c
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Important gcc Options}
+turn on (almost) all warnings
+\begin{verbatim}
+gcc -Wall -ohello hello.c
+\end{verbatim}
+treat warnings as errors
+\begin{verbatim}
+gcc -Werror -ohello hello.c
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{gcc: Useful Tips}
+stop after pre-processing stage and include comments
+\begin{verbatim}
+gcc -E -C hello.c
+\end{verbatim}
+
+show pre-defined/internal macros
+\begin{verbatim}
+$ gcc -E -dM - < /dev/null | cut -c 9- | sort
+[...]
+__SIZEOF_DOUBLE__ 8
+__SIZEOF_FLOAT__ 4
+__SIZEOF_INT__ 4
+__SIZEOF_LONG__ 8
+[...]
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{gcc: Useful Tips}
+Where does the symbol printf come from?
+\begin{verbatim}
+$ gcc -Wl,-y,printf -ohello hello.c
+/lib/libc.so.6: definition of printf
+\end{verbatim}
+Source and further useful tips: http://elinux.org/GCC\_Tips
+\end{frame}
+
+\subsection{The Binutils}
+
+\begin{frame}
+\frametitle{What are the binutils?}
+A collection of programs to create and modify binaries. These programs are not responsible for understanding source code.
+
+The most important tools are:
+\begin{itemize}
+\item \textbf{as}: the GNU assembler
+\item \textbf{ld}: the GNU linker
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Other binutils Programs}
+\begin{itemize}
+\item \textbf{addr2line}: matches binary addresses to source code line numbers
+\item \textbf{gprof}: an execution profiler
+\item \textbf{nm}: lists symbols within object files
+\item \textbf{objcopy}: copies and converts object files
+\item \textbf{objdump}: lists/decodes information within object files
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Other binutils Programs}
+\begin{itemize}
+\item \textbf{ar}: create, modify, extract archives
+\item \textbf{ranlib}: generates the index for an archive file
+\item \textbf{readelf}: displays information within ELF files
+\item \textbf{size}: lists sizes of ELF file sections
+\item \textbf{strip}: removes symbols
+\end{itemize}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Investigating Binaries with objdump}
+\begin{verbatim}
+$ objdump -x /bin/ls
+
+/bin/ls: file format elf64-x86-64
+/bin/ls
+architecture: i386:x86-64, flags 0x00000112:
+EXEC_P, HAS_SYMS, D_PAGED
+start address 0x0000000000402490
+
+Program Header:
+ PHDR off 0x0000000000000040 vaddr [...]
+ filesz 0x00000000000001f8 memsz [...]
+[...]
+Dynamic Section:
+ NEEDED libselinux.so.1
+[...]
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Investigating Binaries with objdump}
+\begin{verbatim}
+[...]
+Version References:
+ required from librt.so.1:
+ 0x09691a75 0x00 07 GLIBC_2.2.5
+[...]
+Sections:
+Idx Name Size VMA [...]
+ 0 .interp 0000001c 000000000040 [...]
+ CONTENTS, ALLOC, LOAD, [...]
+ 1 .note.ABI-tag 00000020 000000000040 [...]
+ CONTENTS, ALLOC, LOAD, [...]
+[...]
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Identifying Library Dependencies with objdump}
+list library dependencies
+\begin{verbatim}
+$ objdump -x /bin/ls | grep NEEDED
+ NEEDED libselinux.so.1
+ NEEDED libacl.so.1
+ NEEDED libc.so.6
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Modifying Binaries with objcopy}
+convert 64-bit ELF to SREC format
+\begin{verbatim}
+objcopy -I elf64-x86-64 -O srec hello hello.srec
+\end{verbatim}
+convert SREC to 64-bit ELF format
+\begin{verbatim}
+objcopy -I srec -O elf64-x86-64 hello.srec hello
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Identifying Source Code Lines with addr2line}
+disassemble program to see addresses
+\begin{verbatim}
+$ objdump -D hello | less
+[...]
+000000000040050c <main>:
+ 40050c: 55 push %rbp
+ 40050d: 48 89 e5 mov %rsp,%rbp
+[...]
+\end{verbatim}
+
+identify source line number for an address
+\begin{verbatim}
+$ addr2line -e hello 40050c
+/home/devel/work/hello.c:4
+\end{verbatim}
+\end{frame}
+
+\subsection{Static Libraries}
+
+\begin{frame}[fragile]
+\frametitle{Using Static Libraries}
+create static library
+\begin{verbatim}
+gcc -c file1.c file2.c
+
+ar cr libhello.a file1.o file2.o
+
+ranlib libhello.a
+\end{verbatim}
+link against static library
+\begin{verbatim}
+gcc -ohello hello.o libhello.a
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Static Builds}
+create a static executable
+\begin{verbatim}
+gcc -static -ohello hello.o -lhello
+\end{verbatim}
+the linker searches for a file libhello.a
+\end{frame}
+
+\subsection{Dynamic Libraries}
+
+\begin{frame}
+\frametitle{\textbf{P}osition \textbf{I}ndependent \textbf{C}ode}
+The -fPIC compiler option tells the compiler to only generate instructions that are position independen (i.e. relative). This means the generated instrutions can be run from any virtual address.
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Using Dynamic (i.e. Shared) Libraries}
+create shared library
+\begin{verbatim}
+gcc -c -fPIC file1.c file2.c
+
+gcc -shared -olibhello.so.0.0.1 file1.o file2.o
+\end{verbatim}
+link against shared library
+\begin{verbatim}
+gcc -ohello hello.c libhello.so.0.0.1
+\end{verbatim}
+Try to start the program. What happens?
+\end{frame}
+
+\begin{frame}
+\frametitle{What is the Dynamic Loader?}
+The dynamic loader (ld-linux) loads the shared libraries needed by a program and then starts that program. It is part of the C library.
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Running Programs}
+\begin{verbatim}
+./hello
+\end{verbatim}
+or
+\begin{verbatim}
+/lib64/ld-linux-x86-64.so.2 ./hello
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Investigating Which Dynamic Loader}
+The dynamic loader is stored in the contents in the ELF .interp section.
+\begin{verbatim}
+$ objdump -s hello | less
+
+hello: file format elf64-x86-64
+
+Contents of section .interp:
+ 400200 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-
+ 400210 7838362d 36342e73 6f2e3200 x86-64.so.2.
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{The Dynamic Loaded: Environment Variables}
+\begin{tabular}{|l|p{5cm}|}
+\hline
+\textbf{Environment Variable} & \textbf{Description} \\
+\hline
+LD\_LIBRARY\_PATH & extra search path for libraries \\
+\hline
+LD\_PRELOAD & list of libraries to be loaded before all others \\
+\hline
+LD\_DEBUG & debug output \\
+\hline
+LD\_TRACE\_LOADED\_OBJECTS & list shared libraries and their load addresses \\
+\hline
+\end{tabular}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The Dynamic Loaded: Environment Variables}
+\begin{verbatim}
+$ LD_DEBUG=help ./hello
+Valid options for the LD_DEBUG environment
+variable are:
+
+ libs display library search paths
+ reloc display relocation processing
+ files display progress for input file
+ symbols display symbol table processing
+ bindings display information about symbol binding
+ versions display version dependencies
+ all all previous options combined
+ statistics display relocation statistics
+ unused determined unused DSOs
+ help display this help message and exit
+\end{verbatim}
+\end{frame}
+
+\begin{frame}
+\frametitle{The Dynamic Loaded: Search Order}
+\begin{enumerate}
+\item DT\_RPATH (ELF dynamic section)
+\item LD\_LIBRARY\_PATH (environment variable)
+\item DT\_RUNPATH (ELF dynamic section)
+\item ld.so.cache (local file)
+\item generic fallbacks: /lib, /usr/lib, etc.
+\end{enumerate}
+\end{frame}
+
+\begin{frame}
+\frametitle{Loader Terminology}
+\begin{itemize}
+\item \textbf{real name}: the filename of the shared library
+\item \textbf{shared object name}: identifies the shared library to load (runtime)
+\item \textbf{linker name}: points to the library to link against (build time, -l)
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The Shared Object Name (soname)}
+The -soname linker option specifies to the linker the shared object name to record in the shared library. It is stored as SONAME in the ELF dynamic section.
+\begin{verbatim}
+gcc -c -fPIC file1.c file2.c
+
+gcc -shared -Wl,-soname,libhello.so.0 \
+ -olibhello.so.0.0.1 file1.o file2.o
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The Shared Object Name (soname)}
+A symbolic link with the shared object name pointing to the shared library (real name) must exist. This is what the dynamic loader is looking for.
+\begin{verbatim}
+libhello.so.0 -> libhello.so.0.0.1
+\end{verbatim}
+The symbolic link should point to the desired library version.
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The Shared Object Name (soname)}
+originally
+\begin{verbatim}
+libhello.so.0 -> libhello.so.0.0.1
+\end{verbatim}
+after minor version update
+\begin{verbatim}
+libhello.so.0 -> libhello.so.0.1.0
+\end{verbatim}
+after major version update
+\begin{verbatim}
+libhello.so.1 -> libhello.so.1.0.0
+\end{verbatim}
+The real name version is typically of the form: major, minor, build.
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{The Shared Object Name (soname)}
+Library dependencies are stored as NEEDED in the ELF dynamic section.
+\begin{verbatim}
+$ objdump -x hello | grep NEEDED
+ NEEDED libhello.so.0
+ NEEDED libc.so.6
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The Linker Name}
+A symbolic link without any version number is usually created that points to the latest major release.
+\begin{verbatim}
+libhello.so -> libhello.so.1
+\end{verbatim}
+This is used by the linker (build time) to locate the correct library specified with -l.
+\begin{verbatim}
+gcc -ohello hello.c -lhello
+\end{verbatim}
+\end{frame}
+
+\begin{frame}
+\frametitle{Loader Terminology}
+\begin{itemize}
+\item \textbf{real name}: libhello.so.0.0.1
+\item \textbf{shared object name}: libhello.so.0
+\item \textbf{linker name}: libhello.so
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{DT\_RUNPATH and DT\_RPATH}
+The -rpath and --enable-new-dtags linker options together specify to the linker a search path to record in the executable binary. It is stored as DT\_RUNPATH in the ELF dynamic section.
+\begin{verbatim}
+gcc -Wl,--enable-new-dtags -Wl,-rpath,/mypath \
+ -ohello hello.c -lhello
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{DT\_RUNPATH and DT\_RPATH}
+The -rpath and --disable-new-dtags linker options together specify to the linker a search path to record in the executable binary. It is stored as DT\_RPATH in the ELF dynamic section.
+\begin{verbatim}
+gcc -Wl,--disable-new-dtags -Wl,-rpath,/mypath \
+ -ohello hello.c -lhello
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Identifying Hard-Coded Search Paths}
+Hard-coded library search paths are are stored as DT\_RUNPATH or DT\_RPATH in the ELF dynamic section (depending on the linker options used).
+\begin{verbatim}
+$ objdump -x hello | grep PATH
+ RUNPATH /mypath
+
+$ objdump -x hello2 | grep PATH
+ RPATH /mypath
+\end{verbatim}
+\end{frame}
+
+\begin{frame}
+\frametitle{The Dynamic Loader}
+Awareness and understanding of the dynamic loader leads to:
+\begin{enumerate}
+\item control where files are located
+\item control which libraries are loaded
+\item faster program loading
+\item cleaner system integration
+\end{enumerate}
+\end{frame}
+
+\subsection{Toolchains (cont.)}
+
+\begin{frame}
+\frametitle{What is a cross-toolchain?}
+\pause
+A toolchain where the architecture of the build machine is different than the architecture of the target machine.
+\end{frame}
+
+\subsection{Automating the Build Process}
+
+\begin{frame}
+\frametitle{GNU make}
+\begin{alertblock}{What is GNU make?}
+GNU make automates and controls build processes.
+\end{alertblock}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Simple Example}
+\begin{verbatim}
+# Makefile
+
+hello: hello.o
+ gcc -o$@ $<
+
+hello.o: hello.c
+ gcc -c -o$@ $<
+
+clean:
+ rm -f hello hello.o
+
+.PHONY: clean
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Rules with Patterns}
+\begin{verbatim}
+hello: hello.o
+ gcc -o$@ $<
+
+%.o: %.c
+ gcc -c -o$@ $<
+
+clean:
+ rm -f hello hello.o
+
+.PHONY: clean
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Variables}
+\begin{verbatim}
+EXE = hello
+OBJ = $(EXE).o
+
+$(EXE): $(OBJ)
+ gcc -o$@ $<
+
+%.o: %.c
+ gcc -c -o$@ $<
+
+clean:
+ rm -f $(EXE) $(OBJ)
+
+.PHONY: clean
+\end{verbatim}
+\end{frame}
+
+\begin{frame}[containsverbatim]
+\frametitle{Pattern Substitution}
+\begin{verbatim}
+SRC = hello.c file1.c file2.c
+OBJS = $(SRC:%.c=%.o)
+
+$(EXE): $(OBJS)
+ gcc -o$@ $<
+
+%.o: %.c
+ gcc -c -o$@ $<
+
+clean:
+ rm -f $(EXE) $(OBJS)
+
+.PHONY: clean
+\end{verbatim}
+\end{frame}
+
+\input{tailpres}