Most of ML code is running as a couple of user tasks on DryOS (look for TASK_CREATE lines in the source code). It calls Canon functions - see platform/stubs.S - to do its job (e.g. to take a picture, to change shutter speed etc).
Some code is called back from DryOS when some events happen (e.g. you change some setting, or you start recording, etc). These are the property handlers (PROP_HANDLER), see
http://magiclantern.wikia.com/wiki/Properties .
The GUI event handlers run in Canon's GUI task (so when a button is pressed, ML code looks at it, and decides whether it's for its own use - e.g. ML menu or shortcut keys - or just passes it to Canon code).
And finally, you can patch small bits of Canon code, usually with cache hacks, or by relocating some code into RAM. This is used, for example, for modifying Canon's startup code in order to load ML. The patching is temporary, the ROM is not altered, just the RAM or CPU cache.
If you want diagrams, you can look here:
http://a1ex.bitbucket.io/ML/states/index.html (these are Canon tasks implemented as state objects).