Technique to Read Source Code
Technique to Read Source Code
Excerpted from http://ruby-hacking-guide.github.io/intro.htm
Any programmer has to read a source code somewhere, but I guess there are not many occasions(机会) that someone teaches you the concrete ways how to read. Why? Does it mean you can naturally read a program if you can write a program?
But I can’t think reading the program written by other people is so easy. In the same way as writing programs, there must be techniques and theories in reading programs. And they are necessary. Therefore, I’d like to expand a general summary of an approach you need to take in reading a source code.
Principles
At first, I mention the principle.
Decide a goal
An important key to reading the source code is to set a concrete goal.
This is a word by the author of Ruby, Matsumoto. Indeed, his word is very convincing(有说服力的) for me. When the motivation is a spontaneous(自发的) idea “Maybe I should read a kernel, at least…”, you would get source code expanded or explanatory books ready on the desk. But not knowing what to do, the studies are to be left untouched. Haven’t you? On the other hand, when you have in mind “I’m sure there is a bug somewhere in this tool. I need to quickly fix it and make it work. Otherwise I will not be able to make the deadline…”, you will probably be able to fix the code in a blink, even if it’s written by someone else. Haven’t you?
The difference in these two cases is motivation you have. In order to know something, you at least have to know what you want to know. Therefore, the first step of all is to figure out what you want to know in explicit words.
However, of course this is not all needed to make it your own “technique”. Because “technique” needs to be a common method that anybody can make use of it by following it. In the following section, I will explain how to bring the first step into the landing place where you achieve the goal finally.
Visualising the goal
Now let us suppose that our final goal is set “Understand all about ruby”. This is certainly considered as “one set goal”, but apparently it will not be useful for reading the source code actually. It will not be a trigger of any concrete action. Therefore, your first job will be to drag down the vague(模糊的) goal to the level of a concrete thing.
Then how can we do it? The first way is thinking as if you are the person who wrote the program. You can utilize your knowledge in writing a program, in this case. For example, when you are reading a traditional “structured” programming (结构化编程) by somebody, you will analyze it hiring the strategies of structured programming too. That is, you will divide the target into pieces, little by little. If it is something circulating in a event loop such as a GUI program, first roughly(大概地) browse the event loop then try to find out the role of each event handler. Or, try to investigate(研究) the “M” of MVC (Model View Controller) first.
Second, it’s good to be aware of the method to analyze. Everybody might have certain analysis methods, but they are often done relying on experience or intuition(直觉). In what way can we read source codes well? Thinking about the way itself and being aware of it are crucially(至关地) important.
Well, what are such methods like? I will explain it in the next section.
Analysis methods
The methods to read source code can be roughly divided into two; one is a static method and the other is dynamic method. Static method is to read and analyze the source code without running the program. Dynamic method is to watch the actual behavior using tools like a debugger.
It’s better to start studying a program by dynamic analysis. That is because what you can see there is the “fact”. The results from static analysis, due to the fact of not running the program actually, may well be “prediction” to a greater or lesser extent(程度). If you want to know the truth, you should start from watching the fact.
Of course, you don’t know whether the results of dynamic analysis are the fact really. The debugger could run with a bug, or the CPU may not be working properly due to overheat. The conditions of your configuration could be wrong. However, the results of static analysis should at least be closer to the fact than dynamic analysis.
Dynamic analysis
Using the target program
You can’t start without the target program. First of all, you need to know in advance what the program is like, and what are expected behaviors.
Following the behavior using the debugger
If you want to see the paths of code execution and the data structure produced as a result, it’s quicker to look at the result by running the program actually than to emulate the behavior in your brain. In order to do so easily, use the debugger.
I would be more happy if the data structure at runtime can be seen as a picture, but unfortunately we can nearly scarcely(几乎没有) find a tool for that purpose (especially few tools are available for free). If it is about a snapshot of the comparatively(相对地) simpler structure, we might be able to write it out as a text and convert it to a picture by using a tool like graphviz (See doc/graphviz.html in the attached CD-ROM). But it’s very difficult to find a way for general purpose and real time analysis.
Tracer
You can use the tracer if you want to trace the procedures that code goes through. In case of C-language, there is a tool named ctrace. For tracing a system call, you can use tools like strace, truss, and ktrace.
Print everywhere
There is a word “printf debugging”. This method also works for analysis other than debugging. If you are watching the history of one variable, for example, it may be easier to understand to look at the dump of the result of the print statements embed(嵌入), than to track the variable with a debugger.
Modifying the code and running it
Say for example, in the place where it’s not easy to understand its behavior, just make a small change in some part of the code or a particular parameter and then re-run the program. Naturally it would change the behavior, thus you would be able to infer the meaning of the code from it.
It goes without saying, you should also have an original binary and do the same thing on both of them.
Static analysis
The importance of names
Static analysis is simply source code analysis. And source code analysis is really an analysis of names. File names, function names, variable names, type names, member names — A program is a bunch of names.
This may seem obvious because one of the most powerful tools for creating abstractions in programming is naming, but keeping this in mind will make reading much more efficient.
Also, we’d like to know about coding rules beforehand(事先) to some extent. For example, in C language, extern function often uses prefix to distinguish the type of functions. And in object-oriented programs, function names sometimes contain the information about where they belong to in prefixes, and it becomes valuable information (e.g. rb_str_length).
Reading documents
Sometimes a document describes the internal structure is included. Especially be careful of a file named HACKING etc.
Reading the directory structure
Looking at in what policy the directories are divided. Grasping the overview such as how the program is structured, and what the parts are.
Reading the file structure
While browsing (the names of) the functions, also looking at the policy of how the files are divided. You should pay attention to the file names because they are like comments whose lifetime is very long.
Additionally, if a file contains some modules in it, for each module the functions to compose it should be grouped together, so you can find out the module structure from the order of the functions.
Investigating abbreviations
As you encounter ambiguous(模棱两可的) abbreviations(缩写), make a list of them and investigate each of them as early as possible. For example, when it is written “GC”, things will be very different depending on whether it means “Garbage Collection” or “Graphic Context”.
Abbreviations for a program are generally made by the methods like taking the initial letters or dropping the vowels(元音). Especially, popular abbreviations in the fields of the target program are used unconditionally(无条件地), thus you should be familiar with them at an early stage(阶段).
Understanding data structure
If you find both data and code, you should first investigate the data structure. In other words, when exploring code in C, it’s better to start with header files. And in this case, let’s make the most of our imagination(想象力) from their filenames. For example, if you find frame.h, it would probably be the stack frame definition.
Also, you can understand many things from the member names of a struct and their types. For example, if you find the member next, which points to its own type, then it will be a linked list. Similarly, when you find members such as parent, children, and sibling, then it must be a tree structure. When prev, it will be a stack.
Understanding the calling relationship between functions
After names, the next most important thing to understand is the relationships between functions. A tool to visualize the calling relationships is especially called a “call graph”, and this is very useful. For this, we’d like to utilize tools.
A text-based tool is sufficient(足够的), but it’s even better if a tool can generate diagrams(图表). However such tool is seldom available (especially few tools are for free). When I analyzed ruby to write this book, I wrote a small command language and a parser(解析器) in Ruby and generated diagrams half-automatically by passing the results to the tool named graphviz.
Reading functions
Reading how it works to be able to explain things done by the function concisely(简明地). It’s good to read it part by part as looking at the figure of the function relationships.
What is important when reading functions is not “what to read” but “what not to read”. The ease of reading is decided by how much we can cut out the codes. What should exactly be cut out? It is hard to understand without seeing the actual example, thus it will be explained in the main part.
Additionally, when you don’t like its coding style, you can convert it by using the tool like indent(缩进).
Experimenting by modifying it as you like
It’s a mystery of human body, when something is done using a lot of parts of your body, it can easily persist in your memory. I think the reason why not a few people prefer using manuscript(手写的) papers to a keyboard is not only they are just nostalgic(怀旧的) but such fact is also related.
Therefore, because merely(仅仅是) reading on a monitor is very ineffective to remember with our bodies, rewrite it while reading. This way often helps our bodies get used to the code relatively soon. If there are names or code you don’t like, rewrite them. If there’s a cryptic(神秘的) abbreviation, substitute (替代) it so that it would be no longer abbreviated.
However, it goes without saying but you should also keep the original source aside and check the original one when you think it does not make sense along the way. Otherwise, you would be wondering for hours because of a simple your own mistake. And since the purpose of rewriting is getting used to and not rewriting itself, please be careful not to be enthusiastic(热情的) very much.
Reading the history
A program often comes with a document which is about the history of changes. For example, if it is a software of GNU, there’s always a file named ChangeLog. This is the best resource to know about “the reason why the program is as it is”.
Alternatively, when a version control system like CVS or SCCS is used and you can access it, its utility value is higher than ChangeLog. Taking CVS as an example, cvs annotate, which displays the place which modified a particular line, and cvs diff, which takes difference from the specified version, and so on are convenient.
Moreover, in the case when there’s a mailing list or a news group for developers, you should get the archives(档案) so that you can search over them any time because often there’s the information about the exact reason of a certain change. Of course, if you can search online, it’s also sufficient.
The tools for static analysis
Since various tools are available for various purposes, I can’t describe them as a whole. But if I have to choose only one of them, I’d recommend global. The most attractive(有吸引力的) point is that its structure allows us to easily use it for the other purposes. For instance, gctags, which comes with it, is actually a tool to create tag files, but you can use it to create a list of the function names contained in a file.
~/src/ruby % gctags class.c | awk '{print $1}'
SPECIAL_SINGLETON
SPECIAL_SINGLETON
clone_method
include_class_new
ins_methods_i
ins_methods_priv_i
ins_methods_prot_i
method_list
:
:
That said, but this is just a recommendation of this author, you as a reader can use whichever tool you like. But in that case, you should choose a tool equipped with at least the following features.
- list up the function names contained in a file
- find the location from a function name or a variable name (It’s more preferable if you can jump to the location)
- function cross-reference
Technique to Read Source Code的更多相关文章
- Tips for newbie to read source code
This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...
- 编程等宽字体Source Code Pro(转)
Source Code Pro - 最佳的免费编程字体之一!来自 Adobe 公司的开源等宽字体下载 每一位程序员都有一套自己喜爱的代码编辑器与编程字体,譬如我们之前就推荐过一款"神 ...
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
- How to build windows azure PowerShell Source Code
Download any version source code of Windows Azure Powershell from https://github.com/Azure/azure-sdk ...
- akka cluster sharding source code 学习 (1/5) 替身模式
为了使一个项目支持集群,自己学习使用了 akka cluster 并在项目中实施了,从此,生活就变得有些痛苦.再配上 apache 做反向代理和负载均衡,debug 起来不要太酸爽.直到现在,我还对 ...
- view class source code with JAD plugin in Eclipse
The default class viewer doesn't decompile the class file so you cannot open and check the source co ...
- Classic Source Code Collected
收藏一些经典的源码,持续更新!!! 1.深度学习框架(Deep Learning Framework). A:Caffe (Convolutional Architecture for Fast Fe ...
- Attach source code to a Netbeans Library Wrapper Module
http://rubenlaguna.com/wp/2008/02/22/attach-source-code-to-a-netbeans-library-wrapper-module/ Attach ...
- convert source code files to pdf format in python
import os import sys def find_file(root_dir, type): dirs_pool = [root_dir] dest_pool = [] def scan_d ...
- Ununtu 12.04 gedit安装插件Source Code Browser
1. 安装ctags: sudo apt-get install exuberant-ctags 2. 打开https://github.com/Quixotix/gedit-source-code- ...
随机推荐
- RabbitMq了解
RibbitMQ MQ优势 MQ的三大主要作用: 应用解耦.异步提速.流量削锋 应用解耦 系统的耦合性越高,容错性就越低,可维护性就越低: 解耦: 如果其中一个系统服务宕机,那么系统的其他服务将也无法 ...
- 深入浅出学习透析Nginx服务器的基本原理和配置指南「Keepalive性能分析实战篇」
Linux系统:Centos 7 x64 Nginx版本:1.11.5 Nginx 是一款面向性能设计的 HTTP 服务器,能反向代理 HTTP,HTTPS 和邮件相关(SMTP,POP3,IMAP) ...
- CheckBox 选中取值以及回填
html: <td align="left" style="word-wrap:break-word;word-break:break-all;" col ...
- JavaEE Day02MySQL
今日内容 数据库的基本概念 MySQL数据库软件 安装 卸载 配置 SQL语句 一.数据库的基本概念 1.数据库DataBase,简称DB 2.什么是数据库? 用于存储和管理数据的仓库 ...
- Kubernetes(k8s)存储管理之数据卷volumes(三):NFS数据卷
目录 一.系统环境 二.前言 三.NFS数据卷 3.1 NFS数据卷概览 3.2 配置NFS服务端以及共享目录 3.3 配置NFS客户端 3.4 创建有NFS卷的pod 一.系统环境 服务器版本 do ...
- angr原理与实践(三)——Arbiter:一种弥合二进制程序漏洞发现中的静态和动态鸿沟
转载请说明出处:信安科研人 please subscribe my official wechat :信安科研人 获取更多安全资讯 原文链接:sec22-vadayath.pdf (usenix. ...
- Flask 终端启动运行
在终端启动 1.首先创建xxxx.py文件(xxxx表示创建的文件名)写入一个小app实例,例如: # 在hello.py文件下创建一个小的FLask app from flask import Fl ...
- (一)elasticsearch 编译和启动
1.准备 先从github官网上clone elasticsearch源码到本地,选择合适的分支.笔者这里选用的是7.4.0(与笔者工作环境使用的分支一致),此版本编译需要jdk11. 2.编译 Re ...
- Ubuntu 配置 Oh-my-zsh
注意 oh-my-zsh 这玩意安装简单.卸载难.维护极其繁琐,动不动就报错.体验一下还可以,我个人建议能不装就不装. 下载 zsh sudo apt install zsh 下载 oh-my-zsh ...
- angular打包出现JavaScript堆内存不足、启动也会内存溢出解决办法\increase-memory-limit' 不是内部或外部命令,
## 打包出现JavaScript堆内存不足 最近打包遇到这种报错 Ineffective mark-compacts near heap limit Allocation failed - Java ...