Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bs
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Peter Gerwinski
bs
Commits
d02785e6
Commit
d02785e6
authored
May 13, 2024
by
Peter Gerwinski
Browse files
Options
Downloads
Patches
Plain Diff
Notizen, Beispiel-Programm und Termine 13.5.2024
parent
08208321
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
20240513/bs-20240513.txt
+153
-0
153 additions, 0 deletions
20240513/bs-20240513.txt
20240513/hello-04.c
+7
-0
7 additions, 0 deletions
20240513/hello-04.c
termine.txt
+13
-0
13 additions, 0 deletions
termine.txt
with
173 additions
and
0 deletions
20240513/bs-20240513.txt
0 → 100644
+
153
−
0
View file @
d02785e6
Von "Hello, world!\n" bis zum Kernel, 15.05.2023, 16:20:31
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- printf ("Hello, world!\n"); wird zu puts ("Hello, world!"); optimiert.
- Quelltext von puts(): apt-get source glibc
- "virtuelle Methoden" in C
- spezielle Compiler-Befehle: __attribute__((..)), weak alias, Pipelining-Optimierung
- plattformunabhängige Programmierung: Präprozessor-"Hook"s
- Kernel-nächste Funktion: write()
- Systemaufruf: _IO_SYSWRITE() --> syscall: spezieller Assembler-Befehl
Hardware-Unterstützung für den Übergang Kernel<-->Userspace
Im Kernel, 06.05.2024, 18:24:25
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fs/read_write.c:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count)
--> ruft ksys_write() auf
--> ruft vfs_write() auf
fs/open.c:
Öffnen der Datei: do_dentry_open()
- bekommt einen inode übergeben,
- ordnet einem Datei-struct den inode zu,
- übergibt die fops (Callbacks) aus dem inode an das Datei-struct.
vfs_write(): Aufruf des Callbacks aus dem Kernel-Modul
if (file->f_op->write)
ret = file->f_op->write(file, buf, count, pos);
Die Funktion inode_permission() aus fs/namei.c prüft, ob geeignete
Zugriffsrechte zum Lesen, Schreiben oder Ausführen gegeben sind.
Vom Syscall-Befehl bis zum Aufruf vom ksys_write(), 13.05.2024, 17:39:34
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/x86/entry/syscall_64.c:
mehrfach: #include <asm/syscalls_64.h>
davor jeweils: #define __SYSCALL(nr, sym) [...]
--> Liste von Externdeklarationen
Aufruf-Funktion x64_sys_call() für Syscall-Funktionen mit großem switch()
historisch: Tabelle mit Zeigern auf Syscall-Funktionen
scripts/syscalltbl.sh:
Skript, das asm/syscalls_64.h aus arch/x86/entry/syscalls/syscall_64.tbl erstellt,
aufgerufen von arch/x86/entry/syscalls/Makefile
(Dieses Makefile macht noch mehr, z.B. Verwaltung der ABIs.)
arch/x86/entry/common.c:
do_syscall_64(struct pt_regs *regs, int nr)
ruft do_syscall_x64(regs, nr) auf,
ruft x64_sys_call() auf.
arch/x86/entry/entry_64.S: (.S = Assembler mit Präprozessor)
Definition einer Funktion entry_SYSCALL_64
Registerinhalte in einem struct abspeichern
Dieser struct ist eine lokale Variable - auf dem Stack.
Jeder push-Befehl reserviert Speicher auf dem Stack
und speichert dort den Inhalt des Registers.
movq %rsp, %rdi
Zeiger auf das Struct ins rdi-Register packen
--> Parameter für C-Funktionsaufruf
movslq %eax, %rsi
"move signed from long to quadword"
32-Bit-Zahl nach 64-Bit-Zahl kopieren, mit Vorzeichen
--> Parameter für C-Funktionsaufruf: Nr. des Syscalls
Finale: Wer ruft entry_SYSCALL_64 auf?
--> Nach der Pause.
_____________________
< Pause bis 18:28 Uhr >
---------------------
\
\
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
Wer ruft entry_SYSCALL_64 auf?
grep -r entry_SYSCALL_64 *
--> arch/x86/kernel/cpu/common.c: wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
Die Funktion void syscall_init(void) enthält:
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
Hier hinterlegen wir die Adresse von entry_SYSCALL_64 (als 64-Bit-Zahl)
in einem internen Prozessorregister, das genau für diesen Aufruf (syscall-Befehl)
zuständig ist.
wrmsrl: In ein solches Register schreiben
MSR_STAR: Nummer des Registers, das dafür zuständig ist, sich die Segmente zu merken
(__KERNEL_CS = Code-Segment des Kernels)
MSR_LSTAR: Nummer des Registers, das dafür zuständig ist, sich das Offset zu merken
--> Die Adresse besteht aus 2 Teilen:
- Segment - Speicherschutzmechanismus: Jedes Programm sieht seinen eigenen Speicher.
- Offset - "normale" Speicheradresse
--> Damit sind wir am Ziel. :-)
Was ist ein Trampolin? 13.05.2024, 18:44:25
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Wikipedia (Begriffsklärung): ein Stück Code, das eine andere Funktion aufruft
void bla (void) // sehr einfaches Trampolin ("wrapper")
{
blubb (42); // Die Funktion, die ich aufrufen will, erwartet einen Parameter
} // ("andere Signatur")
int main (void)
{
do_something_with_callback (bla); // Bibliothek erwartet void-Funktion
} // Beispiel: Sortier-Funktion erwartet
// Vergleichs-Funktion als Callback
Manche Sprachen (z.B. Pascal) erlauben geschachtelte Funktionen, z.B.:
int main (void)
{
int answer = 42;
void bla (void) // sehr einfaches Trampolin ("wrapper")
{
blubb (answer); // Die Funktion, die ich aufrufen will, erwartet einen Parameter
} // ("andere Signatur")
do_something_with_callback (bla); // Bibliothek erwartet void-Funktion
}
Problem: bla() wird von "außen" (z.B. Bibliothek) aufgerufen.
Die Variable answer ist dort aber nicht bekannt.
--> Eine Wrapper-Funktion ist ungeeignet, da der beim Aufruf aktuelle Wert
von "answer" nicht zur Compile-Zeit, sondern erst zur Laufzeit bekannt ist.
Lösung (Trampolin): Ausführung von Code auf dem Stack
Der Aufrufer (hier: main()) erzeugt spontan eine neue Funktion.
Die braucht Speicherplatz. --> Auf dem Stack reservieren.
Neues Problem: Ausführbarer Code auf dem Stack ist ein Sicherheitsrisiko.
--> Wird heutzutage mit Hardware-Unterstützung verhindert.
Neue Lösung: sehr aufwendig
"Mit Objektorientierung wird alles gut."
Wenn die Bibliothek mitspielt, kann man ihr ein Objekt übergeben --> Problem gelöst
--> "command pattern"
This diff is collapsed.
Click to expand it.
20240513/hello-04.c
0 → 100644
+
7
−
0
View file @
d02785e6
#include
<unistd.h>
int
main
(
void
)
{
write
(
1
,
"Hello, world!
\n
"
,
14
);
return
0
;
}
This diff is collapsed.
Click to expand it.
termine.txt
0 → 100644
+
13
−
0
View file @
d02785e6
Mo 22.07. 11:00 CVH: Präsentationen bs/nit
Wer sich jetzt zur Prüfung anmeldet,
muß bis zum 20.9.2024 sowohl eine Präsentation gehalten
als auch die Endfassung der Dokumentation abgegeben haben.
Wer das nicht schafft, sollte sich rechtzeitig (also vermutlich
bis 1 Woche vor dem 20.9.2024) wieder von der Prüfung abmelden.
Ansonsten gilt die Prüfung als "nicht bestanden".
Wir werden dafür sorgen, daß man sich in jedem Semester
für die Prüfung wieder anmelden kann (anstatt, wie bisher,
nur in jedem Sommersemester).
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment