9.2 הלינקר תרגול
תרגול - הלינקר¶
תרגיל 1 - פתרון סמלים ידני¶
צרו שלושה קבצים:
// main.c
#include <stdio.h>
extern int counter;
void increment(void);
void print_counter(void);
int main() {
print_counter();
increment();
increment();
increment();
print_counter();
return 0;
}
// printer.c
#include <stdio.h>
extern int counter;
void print_counter(void) {
printf("Counter = %d\n", counter);
}
- קמפלו כל קובץ בנפרד ל-
.oובדקו את הסמלים של כל קובץ עםnm. לכל קובץ, רשמו אילו סמלים הוא מגדיר (T/D) ואילו הוא צריך (U). - חברו את שלושת הקבצים לקובץ הרצה והריצו. מה הפלט?
- מה יקרה אם נשמיט את
counter.oמהלינקוג'? נסו והסבירו את השגיאה. - מה יקרה אם נשמיט את
printer.o? נסו והסבירו.
תרגיל 2 - סמלים חזקים וחלשים¶
צרו שני קבצים:
- קמפלו וחברו את שני הקבצים. מה הפלט?
- שנו את
weak.cכך ש-int value;יהפוך ל-int value = 99;. מה קורה כשמנסים לחבר? - הסבירו: למה במקרה הראשון הלינקר לא נתן שגיאה, אבל במקרה השני כן?
- איך תפתרו את הבעיה אם אתם צריכים משתנה
valueבשני הקבצים אבל כל קובץ צריך את הערך שלו?
תרגיל 3 - יצירת ספריה סטטית¶
צרו ספריה סטטית שמממשת פעולות על מחרוזות:
// mystring.h
#ifndef MYSTRING_H
#define MYSTRING_H
int my_strlen(const char *s);
char *my_strcpy(char *dest, const char *src);
int my_strcmp(const char *s1, const char *s2);
void my_strrev(char *s); // היפוך מחרוזת
#endif
- כתבו את המימוש של כל ארבע הפונקציות בקובץ
mystring.c(בלי להשתמש בפונקציות של libc). - צרו ספריה סטטית
libmystring.aמקובץ האובייקט. - כתבו תוכנית
main.cשמשתמשת בכל ארבע הפונקציות ומדפיסה תוצאות. - קמפלו את התוכנית עם
-L. -lmystring. - הריצו
ar -t libmystring.aכדי לראות את תוכן הספריה. - הריצו
nm libmystring.aכדי לראות את הסמלים בספריה.
תרגיל 4 - בעיות סדר ספריות¶
צרו שלושה קבצים שתלויים אחד בשני:
// liba.c
#include <stdio.h>
int func_b(int x); // מוגדר ב-libb
int func_a(int x) {
printf("func_a(%d)\n", x);
if (x > 0) return func_b(x - 1);
return x;
}
// libb.c
int func_a(int x); // מוגדר ב-liba
int func_b(int x) {
if (x > 0) return func_a(x - 1);
return x * 2;
}
// main.c
#include <stdio.h>
int func_a(int x);
int main() {
printf("Result: %d\n", func_a(5));
return 0;
}
- צרו שתי ספריות סטטיות:
liba.a(מ-liba.o) ו-libb.a(מ-libb.o). - נסו לחבר:
gcc main.o -L. -la -lb -o program. מה קורה? - נסו בסדר הפוך:
gcc main.o -L. -lb -la -o program. מה קורה? - מצאו דרך לחבר בהצלחה (רמז:
--start-group/--end-groupאו חזרה על ספריות).
תרגיל 5 - חקירת הlinker script¶
- הריצו
ld --verboseכדי לראות את הlinker script של ברירת המחדל. מצאו: - מהי נקודת הכניסה (ENTRY)?
- מה כתובת ההתחלה של סגמנט הקוד?
-
אילו סקשנים נכנסים לסגמנט הקוד (text segment)?
-
כתבו תוכנית פשוטה, קמפלו אותה, ובדקו:
מה הכתובת של_start? מה הכתובת שלmain? מי קודם? -
הריצו
gcc main.c -Wl,-Map=output.map -o program. פתחו אתoutput.mapומצאו: - איפה סקשן
.textהוצב - איפה סקשן
.dataהוצב - מה הגודל של כל סקשן