How to Crash a Macbook

I found a rather easy way to crash a Mac.

First, You need to have two or more partitions.
Second, delete the directory /var/vm.
Third, create a symbolic link. ln -s /The/Other/partition/directory
/var/vm. /The/Other/partition/directory is at another partition other
than the one where /var is at.

Then you continue to use your Mac for some time, you will find at least
one program crashes. Then you may decide to reboot your mac to see
whether the program will become normal, you must find that your mac
could not start again.

Don't be panic. You can solve it. Use your Mac installation disc. But
you don't need to reinstall your system. You can open a terminal, delete
the symbolic link /var/vm and create a new directory /var/vm. Then you
will find your crazy mac become normal.
Why?
I think this should be a bug in Mac.
/var/vm is the directory where the swap files are at. Mac seems to use
this directory before it mounts the other partition. So if /var/vm is a
symbolic link to other partition, Mac could not use /var/vm at all when
it starts, because other partitions are not available yet.

And the swap files can become very large. They may use up the all the
disk space. They will make the system rather slow.

How GDB implements break command

When you want to add a breakpoint, you usually use the command "break". GDB will first parse the command, and find the address, as described here. But what's the next?

GDB will create a breakpoint after it parses the command and finds the address and the symbol table . The breakpoint is represented by the type struct breakpoint (see create_breakpoint). At this point, GDB only creates the structure and adds it to the collection of breakpoints. It does not really insert them. The insertion only occurs before the inferior starts to run. For example, when the function proceed is called, which will make the inferior run, it will call insert_breakpoints to insert the breakpoints in the collection of breakpoints.
When a breakpoint is hit, a trap, a signal or whatever will cause the inferior to stop. At this point, GDB will take over of it and handle the event first. It calls the function handle_inferior_event. It will check the reason why the inferior stops. And it will detect whether there is a breakpoint hit. Remember you can add conditions to breakpoints. If the conditions is false, even if there is a breakpoint hit, GDB won't do anything. GDB stops the inferior only when a breakpoint is hit and the conditions are true.

How Does GDB Parse Breakpoint Location

When you use GDB, you can add breakpoints, giving it some arguments. For example, you can specify the location by giving line numbers, function names, variable names, etc. you can also add conditions. When the condition is met, GDB will pause the inferior when the breakpoint is hit. But how does GDB find out the address?

Let's look at the file gdb/breakpoint.c. It implements the command "break" in GDB. Actually, the function break_command_really does parse the command arguments, converts the arguments to address, and adds the breakpoint.

It first calls do_captured_parse_breakpoint, which will eventually calls parse_breakpoint_sals to parse the argument of the command break and return the address specification in the form of the type symtabs_and_lines.

symtabs_and_lines is a struct. It represents a sequences of symtab_and_line. symtab_and_line is a struct containing the information of a symbol table, a line number, the pc, and etc.

The function parse_breakpoint_sals will find out the address, the line number, the symbol table, and the section of the given location, and store them in the variable sal which is of type struct symbol_and_line. What it does is dependent on whether the location is specified.

It is quite simple if the location is not specified. That is, the command is "break" but "break 47". The function just simply assigns the defaults to sal. These defaults are stored in the variables default_breakpoint_pc, default_breakpoint_line, default_breakpoint_symtab. These variables are set by the function print_stack_frame.

In the other case where the location is given, it will call decode_line_1 to parse the location. Considering the location can be an address, a line number, a function, etc, the function decode_line_1 uses different methods to parse them.
For the address, it calls decode_indirect.
If you specify an Object-C method or a compound method without a file name ("A::B::func", "[object func]", etc), it will search the symbol table for the symbol of the function.
If you specify a file name (e.g. "file.c:47"), it first reads the symbol table of that file. Then it calls decode_all_digits if the location is a number (e.g. a line number) or decode_variable if the location is a name (a function or a variable).

The function decode_variable merely looks up the symbol of the variable in the symbol table. GDB uses the struct symbol to represent a function, and a variable, etc. Each symbol has an address. A function address, unlike a local variable address, is known when the when the program is loaded. So function decode_variable can extract the address from the symbol easily.

The function decode_all_digits will calculate the line number (if it begins with "+" or "-", meaning relative to the current line number) and finds out the symbol table which will be used to calculate the address. It also sets the flag explicit_line to 1. And when to find the address of the given line number? it is finished in the function breakpoint_sals_to_pc.

Also, GDB will create a canonical string, which is similar to "file.c:123".

When all these functions return, break_command_really will call breakpoint_sals_to_pc, which will call sals_to_pc, to extract information from the struct symtab_and_line and return the address.

What sals_to_pc does is to read each item in the symbol table and to compare the line of the item with the given line. And it will find the exact match item or the approximate one. There is a line table in each symbol table. It is a mapping of a line number to an address. GDB uses this technique to find out the address of a given line number.

Once the address is found, the function sals_to_pc will find the section in which this line is.