GCC provides a low-level runtime library, libgcc.a or libgcc_s.so.1 on some platforms. GCC generates calls to routines in this library automatically, whenever it needs to perform some operation that is too complicated to emit inline code for.
Most of the routines in libgcc handle arithmetic operations that the target processor cannot perform directly. This includes integer multiply and divide on some machines, and all floating-point and fixed-point operations on other machines. libgcc also includes routines for exception handling, and a handful of miscellaneous operations.
libgcc1 exists primarily conceptually. It is the basic set of
operations which can not be reasonably implemented using other
operations. In the good old days libgcc1 was built using the other
compiler on your system. Since these days there is generally no other
compiler, most targets provide assembler code to perform the operations.
For example, see config/arm/lib1funcs.asm.
libgcc2, conversely, is the set of operations which can be implemented
reasonably. For example, if you have a 32-bit add instruction, it’s
easy to use it to implement 64-bit addition. This code appears in
gcc/libgcc2.c. On many processors it is possible to optimize using
instructions which are not avaliable in C, such as add-with-carry; those
optimizations are written in gcc/longlong.h.