DAY 22
0
Software Development

## 第二十二日：objdump 實作之完結

### 回顧：設計大綱

1. 讀取 ELF 檔案
2. `.symtab` 或是同樣屬性的區段取得標籤
1. 依位址排序完成
3. 取出 `.text` 區段內容
1. 將相對應的區段的內容餵給 rvgc 函式庫的 `BinToInst`
4. 印出回傳的內容，將標籤嵌入在正確的位置

### 重返 rvgc 函式庫

#### BinToInst 函式

``````func BinToInst(bin []byte) string {

nm, t := instType(bin)
rd := bits2regs[(bin[1]&0x0f)<<1+bin[0]>>7]
rs1 := bits2regs[(bin[2]&0x0f)<<1+bin[1]>>7]
rs2 := bits2regs[(bin[2]&0xf0)>>4+(bin[2]&0x01)<<4]
switch t {
case RV_INST_R_TYPE:
return nm + " " + rd + "," + rs1 + "," + rs2
case RV_INST_I_TYPE:
imm := bin[2]>>4 + bin[3]<<4
return nm + " " + rd + "," + rs1 + "," + strconv.FormatUint(imm, 16)
case RV_INST_S_TYPE:
imm := (bin[3]&0xfe)<<5 + (bin[1]&0x0f)<<1 + bin[0]>>7
return nm + " " + rs1 + "," + rs2 + "," + strconv.FormatUint(imm, 16)
case RV_INST_B_TYPE:
imm := ((bin[3]&0x80)<<4 + (bin[0]&0x80)<<3 + (bin[3]&0x7e)<<3 + (bin[1] & 0x0f))<<1
return nm + " " + rs1 + "," + rs2 + "," + strconv.FormatUint(imm, 16)
case RV_INST_U_TYPE:
imm := bin[3]<<24 + bin[2]<<16 + (bin[1]&0xf0)<<8
return nm + " " + rd + "," + strconv.FormatUint(imm, 16)
case RV_INST_J_TYPE:
default:
return "noimp"
}
}
``````

#### instType 函式

``````func instType(bin []byte) (string, RV_INST_TYPE) {
var nm string
var t RV_INST_TYPE

switch RV_OPCODE_TYPE(bin[0] & 0x7f) {
``````

``````        case RV_OPCODE_LOAD:
t = RV_INST_R_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
nm = "lb"
case 1:
nm = "lh"
case 2:
nm = "lw"
case 3:
nm = "ld"
case 4:
nm = "lbu"
case 5:
nm = "lhu"
case 6:
nm = "lwu"
}
return nm, t
``````

``````        case RV_OPCODE_OP_IMM:
t = RV_INST_I_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
case 1:
nm = "slli"
case 2:
nm = "slti"
case 3:
nm = "sltiu"
case 4:
nm = "ori"
case 5:
if bin[3]&0x40 == 0 {
nm = "srli"
} else {
nm = "srai"
}
case 6:
nm = "xori"
case 7:
nm = "andi"
}
return nm, t
``````

``````        case RV_OPCODE_AUIPC:
return "auipc", RV_INST_U_TYPE
``````

``````        case RV_OPCODE_OP_IMM_32:
t = RV_INST_I_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
case 1:
nm = "slliw"
case 5:
if bin[3]&0x40 == 0 {
nm = "srliw"
} else {
nm = "sraiw"
}
}
return nm, t
case RV_OPCODE_STORE:
t = RV_INST_S_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
nm = "sb"
case 1:
nm = "sh"
case 2:
nm = "sw"
case 3:
nm = "sd"
}
return nm, t
case RV_OPCODE_OP:
t = RV_INST_R_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
if bin[3]&0x40 == 0 {
} else {
nm = "sub"
}
case 1:
nm = "sll"
case 2:
nm = "slt"
case 3:
nm = "sltu"
case 4:
nm = "or"
case 5:
if bin[3]&0x40 == 0 {
nm = "srl"
} else {
nm = "sra"
}
case 6:
nm = "xor"
case 7:
nm = "and"
}
return nm, t
case RV_OPCODE_LUI:
return "lui", RV_INST_U_TYPE
case RV_OPCODE_OP_32:
t = RV_INST_R_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
if bin[3]&0x40 == 0 {
} else {
nm = "subw"
}
case 1:
nm = "sllw"
case 5:
if bin[3]&0x40 == 0 {
nm = "srlw"
} else {
nm = "sraw"
}
}
return nm, t
case RV_OPCODE_BRANCH:
t = RV_INST_B_TYPE
switch (bin[1] & 0x70) >> 4 {
case 0:
nm = "beq"
case 1:
nm = "bne"
case 4:
nm = "blt"
case 5:
nm = "bgt"
case 6:
nm = "bltu"
case 7:
nm = "bgtu"
}
return nm, t
case RV_OPCODE_JALR:
return "jalr", RV_INST_I_TYPE
case RV_OPCODE_JAL:
return "jal", RV_INST_J_TYPE
case RV_OPCODE_SYSTEM:
return "ecall", RV_INST_NONE
}
return "noimp", RV_INST_NONE
}
``````

### 輸出

``````addi sp,sp,f0
sb t0,sp,0
sb t0,sp,1
sb t0,sp,2
sb t0,sp,3
ecall
bne t1,zero,e8
lui t2,44434000
sw t2,sp,0
ecall
ecall
``````

### 小結

• 連結是什麼？
• ELF 檔如何支援連結的功能？
• RISC-V 架構在連結上有什麼特殊的地方？
• 程式檔頭是什麼？