02 elf 的 binary 解析

news2024/9/24 5:31:33

前言

需求来自于 linux binary 的执行分析, 以及一些反编译工具的实现 

比如 readelf, hopper disassemble 什么的 

主要的目的是 更加详细了解 elf 的文件格式 

为 后续的一些 理解做准备 

elf 解析 

elf 文件主要分为 四个部分 

elfHeader, programHeaders, segments, segmentHeaders

我们这里查看的 elf 为一个  简单的 HelloWorld 生成的一个 elf 文件 

#include "stdio.h"

int main(int argc, char** argv) {

int x = 2;
int y = 3;
int z = x + y;

printf(" x + y = %d\n ", z);

}

readelf 解析如下 

root@ubuntu:~# readelf -a Test01Sum 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400430
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6624 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 28

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000400254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000400274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400298  00000298
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           00000000004002b8  000002b8
       0000000000000060  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000400318  00000318
       000000000000003f  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           0000000000400358  00000358
       0000000000000008  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000400360  00000360
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400380  00000380
       0000000000000018  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000400398  00000398
       0000000000000030  0000000000000018  AI       5    24     8
  [11] .init             PROGBITS         00000000004003c8  000003c8
       000000000000001a  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         00000000004003f0  000003f0
       0000000000000030  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         0000000000400420  00000420
       0000000000000008  0000000000000000  AX       0     0     8
  [14] .text             PROGBITS         0000000000400430  00000430
       00000000000001b2  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         00000000004005e4  000005e4
       0000000000000009  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         00000000004005f0  000005f0
       0000000000000012  0000000000000000   A       0     0     4
  [17] .eh_frame_hdr     PROGBITS         0000000000400604  00000604
       0000000000000034  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         0000000000400638  00000638
       00000000000000f4  0000000000000000   A       0     0     8
  [19] .init_array       INIT_ARRAY       0000000000600e10  00000e10
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .fini_array       FINI_ARRAY       0000000000600e18  00000e18
       0000000000000008  0000000000000000  WA       0     0     8
  [21] .jcr              PROGBITS         0000000000600e20  00000e20
       0000000000000008  0000000000000000  WA       0     0     8
  [22] .dynamic          DYNAMIC          0000000000600e28  00000e28
       00000000000001d0  0000000000000010  WA       6     0     8
  [23] .got              PROGBITS         0000000000600ff8  00000ff8
       0000000000000008  0000000000000008  WA       0     0     8
  [24] .got.plt          PROGBITS         0000000000601000  00001000
       0000000000000028  0000000000000008  WA       0     0     8
  [25] .data             PROGBITS         0000000000601028  00001028
       0000000000000010  0000000000000000  WA       0     0     8
  [26] .bss              NOBITS           0000000000601038  00001038
       0000000000000008  0000000000000000  WA       0     0     1
  [27] .comment          PROGBITS         0000000000000000  00001038
       0000000000000035  0000000000000001  MS       0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  000018d2
       000000000000010c  0000000000000000           0     0     1
  [29] .symtab           SYMTAB           0000000000000000  00001070
       0000000000000648  0000000000000018          30    47     8
  [30] .strtab           STRTAB           0000000000000000  000016b8
       000000000000021a  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000072c 0x000000000000072c  R E    200000
  LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x0000000000000228 0x0000000000000230  RW     200000
  DYNAMIC        0x0000000000000e28 0x0000000000600e28 0x0000000000600e28
                 0x00000000000001d0 0x00000000000001d0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x0000000000000604 0x0000000000400604 0x0000000000400604
                 0x0000000000000034 0x0000000000000034  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
  GNU_RELRO      0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x00000000000001f0 0x00000000000001f0  R      1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .jcr .dynamic .got 

Dynamic section at offset 0xe28 contains 24 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x4003c8
 0x000000000000000d (FINI)               0x4005e4
 0x0000000000000019 (INIT_ARRAY)         0x600e10
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x600e18
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x400318
 0x0000000000000006 (SYMTAB)             0x4002b8
 0x000000000000000a (STRSZ)              63 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x601000
 0x0000000000000002 (PLTRELSZ)           48 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400398
 0x0000000000000007 (RELA)               0x400380
 0x0000000000000008 (RELASZ)             24 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x400360
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x400358
 0x0000000000000000 (NULL)               0x0

Relocation section '.rela.dyn' at offset 0x380 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600ff8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x398 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000601018  000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
000000601020  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

Symbol table '.symtab' contains 67 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400238     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000400254     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000400274     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000400298     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000004002b8     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000400318     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000400358     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000400360     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000400380     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000400398     0 SECTION LOCAL  DEFAULT   10 
    11: 00000000004003c8     0 SECTION LOCAL  DEFAULT   11 
    12: 00000000004003f0     0 SECTION LOCAL  DEFAULT   12 
    13: 0000000000400420     0 SECTION LOCAL  DEFAULT   13 
    14: 0000000000400430     0 SECTION LOCAL  DEFAULT   14 
    15: 00000000004005e4     0 SECTION LOCAL  DEFAULT   15 
    16: 00000000004005f0     0 SECTION LOCAL  DEFAULT   16 
    17: 0000000000400604     0 SECTION LOCAL  DEFAULT   17 
    18: 0000000000400638     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000600e10     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000600e18     0 SECTION LOCAL  DEFAULT   20 
    21: 0000000000600e20     0 SECTION LOCAL  DEFAULT   21 
    22: 0000000000600e28     0 SECTION LOCAL  DEFAULT   22 
    23: 0000000000600ff8     0 SECTION LOCAL  DEFAULT   23 
    24: 0000000000601000     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000601028     0 SECTION LOCAL  DEFAULT   25 
    26: 0000000000601038     0 SECTION LOCAL  DEFAULT   26 
    27: 0000000000000000     0 SECTION LOCAL  DEFAULT   27 
    28: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    29: 0000000000600e20     0 OBJECT  LOCAL  DEFAULT   21 __JCR_LIST__
    30: 0000000000400460     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    31: 00000000004004a0     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    32: 00000000004004e0     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    33: 0000000000601038     1 OBJECT  LOCAL  DEFAULT   26 completed.7594
    34: 0000000000600e18     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fin
    35: 0000000000400500     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    36: 0000000000600e10     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_
    37: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS Test01Sum.c
    38: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    39: 0000000000400728     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    40: 0000000000600e20     0 OBJECT  LOCAL  DEFAULT   21 __JCR_END__
    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    42: 0000000000600e18     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end
    43: 0000000000600e28     0 OBJECT  LOCAL  DEFAULT   22 _DYNAMIC
    44: 0000000000600e10     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start
    45: 0000000000400604     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    46: 0000000000601000     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_
    47: 00000000004005e0     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    48: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
    49: 0000000000601028     0 NOTYPE  WEAK   DEFAULT   25 data_start
    50: 0000000000601038     0 NOTYPE  GLOBAL DEFAULT   25 _edata
    51: 00000000004005e4     0 FUNC    GLOBAL DEFAULT   15 _fini
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    54: 0000000000601028     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
    55: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    56: 0000000000601030     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
    57: 00000000004005f0     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    58: 0000000000400570   101 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    59: 0000000000601040     0 NOTYPE  GLOBAL DEFAULT   26 _end
    60: 0000000000400430    42 FUNC    GLOBAL DEFAULT   14 _start
    61: 0000000000601038     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    62: 0000000000400526    67 FUNC    GLOBAL DEFAULT   14 main
    63: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    64: 0000000000601038     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    65: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    66: 00000000004003c8     0 FUNC    GLOBAL DEFAULT   11 _init

Version symbols section '.gnu.version' contains 4 entries:
 Addr: 0000000000400358  Offset: 0x000358  Link: 5 (.dynsym)
  000:   0 (*local*)       2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)   0 (*local*)    

Version needs section '.gnu.version_r' contains 1 entries:
 Addr: 0x0000000000400360  Offset: 0x000360  Link: 6 (.dynstr)
  000000: Version: 1  File: libc.so.6  Cnt: 1
  0x0010:   Name: GLIBC_2.2.5  Flags: none  Version: 2

Displaying notes found at file offset 0x00000254 with length 0x00000020:
  Owner                 Data size	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 2.6.32

Displaying notes found at file offset 0x00000274 with length 0x00000024:
  Owner                 Data size	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 676de8fa9bce03059433028da409bb25c151f668

hopper disassemble 解析如下, 截取片段 

相关实体

ElfFile 

/**
 * ElfFile
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2022-09-25 11:08
 */
@Data
public class ElfFile implements Serializable {

    private ElfHeader header;
    private List<ElfProgramHeader> programHeaders;
    private Integer[] sectionBytes;
    private List<ElfSegment> segments;
    private List<ElfSectionHeader> sectionHeaders;

    @Field(sort = 0, name = "header", dataType = DataType.GENERIC_BEAN, desc = "header", version = {1})
    public ElfHeader getHeader() {
        return header;
    }

    @Field(sort = 10, name = "programHeaders", dataType = DataType.GENERIC_BEAN_COLLECTION, desc = "programHeaders", version = {1})
    public List<ElfProgramHeader> getprogramHeaders() {
        return programHeaders;
    }

    @Field(sort = 20, name = "sectionBytes", dataType = DataType.BYTE_ARRAY, desc = "sectionBytes", version = {1})
    public Integer[] getSectionBytes() {
        return sectionBytes;
    }

    public void setSegments(List<ElfSegment> segments) {
        this.segments = segments;
    }

    @Field(sort = 30, name = "sectionHeaders", dataType = DataType.GENERIC_BEAN_COLLECTION, desc = "sectionHeaders", version = {1})
    public List<ElfSectionHeader> getSectionHeaders() {
        return sectionHeaders;
    }

}

ElfHeader

/**
 * ElfHeader
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2022-09-25 11:08
 */
@Data
public class ElfHeader implements Serializable {

    private String ident;
    private Integer type;
    private Integer machine;
    private Integer version;
    private Long entry;
    private Long phoff;
    private Long shoff;
    private Integer flags;
    private Integer ehsize;
    private Integer phentsize;
    private Integer phnum;
    private Integer shentsize;
    private Integer shnum;
    private Integer shstrndx;

    private Long offsetInFile;

    @Field(sort = 0, name = "ident", dataType = DataType.CHARSET_ENCODING_WITH_FIXED_LEN_STRING, lengthInBytes = 16, desc = "ident", version = {1})
    public String getIdent() {
        return ident;
    }

    @Field(sort = 10, name = "type", dataType = DataType.UNSIGNED_WORD, desc = "type", bigEndian = false, version = {1})
    public Integer getType() {
        return type;
    }

    @Field(sort = 20, name = "machine", dataType = DataType.UNSIGNED_WORD, desc = "machine", bigEndian = false, version = {1})
    public Integer getMachine() {
        return machine;
    }

    @Field(sort = 30, name = "version", dataType = DataType.DWORD, desc = "version", bigEndian = false, version = {1})
    public Integer getVersion() {
        return version;
    }

    @Field(sort = 40, name = "entry", dataType = DataType.QWORD, desc = "entry", bigEndian = false, version = {1})
    public Long getEntry() {
        return entry;
    }

    @Field(sort = 50, name = "phoff", dataType = DataType.QWORD, desc = "phoff", bigEndian = false, version = {1})
    public Long getPhoff() {
        return phoff;
    }

    @Field(sort = 60, name = "shoff", dataType = DataType.QWORD, desc = "shoff", bigEndian = false, version = {1})
    public Long getShoff() {
        return shoff;
    }

    @Field(sort = 70, name = "flags", dataType = DataType.DWORD, desc = "flags", bigEndian = false, version = {1})
    public Integer getFlags() {
        return flags;
    }

    @Field(sort = 80, name = "ehsize", dataType = DataType.UNSIGNED_WORD, desc = "ehsize", bigEndian = false, version = {1})
    public Integer getEhsize() {
        return ehsize;
    }

    @Field(sort = 90, name = "phentsize", dataType = DataType.UNSIGNED_WORD, desc = "phentsize", bigEndian = false, version = {1})
    public Integer getPhentsize() {
        return phentsize;
    }

    @Field(sort = 100, name = "phnum", dataType = DataType.UNSIGNED_WORD, desc = "phnum", bigEndian = false, version = {1})
    public Integer getPhnum() {
        return phnum;
    }

    @Field(sort = 110, name = "shentsize", dataType = DataType.UNSIGNED_WORD, desc = "shentsize", bigEndian = false, version = {1})
    public Integer getShentsize() {
        return shentsize;
    }

    @Field(sort = 120, name = "shnum", dataType = DataType.UNSIGNED_WORD, desc = "shnum", bigEndian = false, version = {1})
    public Integer getShnum() {
        return shnum;
    }

    @Field(sort = 130, name = "shstrndx", dataType = DataType.UNSIGNED_WORD, desc = "shstrndx", bigEndian = false, version = {1})
    public Integer getShstrndx() {
        return shstrndx;
    }

    public JSONObject getHexRelated() {
        JSONObject result = new JSONObject();
        result.put("entry", "0x" + Long.toHexString(entry));
        result.put("phoff", "0x" + Long.toHexString(phoff));
        result.put("shoff", "0x" + Long.toHexString(shoff));
        return result;
    }

    public String toString() {
        return JSON.toJSONString(this);
    }

}

ElfProgramHeader

/**
 * ElfPhHeader
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 10:18
 */
@Data
public class ElfProgramHeader implements Serializable {

    private Integer type;
    private Integer flags;
    private Long offset;
    private Long vaddr;
    private Long paddr;
    private Long fileSz;
    private Long memSz;
    private Long align;

    private Long offsetInFile;

    @Field(sort = 0, name = "type", dataType = DataType.DWORD, desc = "type", bigEndian = false, version = {1})
    public Integer getType() {
        return type;
    }

    @Field(sort = 10, name = "flags", dataType = DataType.DWORD, desc = "flags", bigEndian = false, version = {1})
    public Integer getFlags() {
        return flags;
    }

    @Field(sort = 20, name = "offset", dataType = DataType.QWORD, desc = "offset", bigEndian = false, version = {1})
    public Long getOffset() {
        return offset;
    }

    @Field(sort = 30, name = "vaddr", dataType = DataType.QWORD, desc = "vaddr", bigEndian = false, version = {1})
    public Long getVaddr() {
        return vaddr;
    }

    @Field(sort = 40, name = "paddr", dataType = DataType.QWORD, desc = "paddr", bigEndian = false, version = {1})
    public Long getPaddr() {
        return paddr;
    }

    @Field(sort = 50, name = "fileSz", dataType = DataType.QWORD, desc = "fileSz", bigEndian = false, version = {1})
    public Long getFileSz() {
        return fileSz;
    }

    @Field(sort = 60, name = "memSz", dataType = DataType.QWORD, desc = "memSz", bigEndian = false, version = {1})
    public Long getMemSz() {
        return memSz;
    }

    @Field(sort = 70, name = "align", dataType = DataType.QWORD, desc = "align", bigEndian = false, version = {1})
    public Long getAlign() {
        return align;
    }

    public JSONObject getHexRelated() {
        JSONObject result = new JSONObject();
        result.put("offset", "0x" + Long.toHexString(offset));
        result.put("vaddr", "0x" + Long.toHexString(vaddr));
        result.put("paddr", "0x" + Long.toHexString(paddr));
        result.put("fileSz", "0x" + Long.toHexString(fileSz));
        result.put("memSz", "0x" + Long.toHexString(memSz));
        result.put("offsetInFile", "0x" + Long.toHexString(offsetInFile));
        return result;
    }

    public String toString() {
        return JSON.toJSONString(this);
    }

}

ElfSegment

/**
 * ElfSegment
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:30
 */
@Data
public class ElfSegment implements Serializable {

    protected String name;

    protected Integer[] bytes;

    protected Long offsetInFile;

    @Override
    public String toString() {
        List<String> toStringNames = Arrays.asList(".comment", ".dynstr", ".shstrtab", ".strtab");
        if (toStringNames.contains(name)) {
            return name + " " + ElfFileCodec.formatOffset(getOffsetInFile()) + " " + new String(ElfFileCodec.transferBytes(bytes));
        }

        return name + " " + ElfFileCodec.formatOffset(getOffsetInFile()) + " " + ElfFileCodec.toString(bytes);
    }

}

ElfSectionHeader 

/**
 * ElfPhHeader
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 10:18
 */
@Data
public class ElfSectionHeader implements Serializable {

    private Integer name;
    private Integer type;
    private Long flags;
    private Long address;
    private Long offset;
    private Long size;
    private Integer link;
    private Integer info;
    private Long addrAlign;
    private Long entrySize;

    @Field(sort = 0, name = "name", dataType = DataType.DWORD, desc = "name", bigEndian = false, version = {1})
    public Integer getName() {
        return name;
    }

    @Field(sort = 10, name = "type", dataType = DataType.DWORD, desc = "type", bigEndian = false, version = {1})
    public Integer getType() {
        return type;
    }

    @Field(sort = 20, name = "flags", dataType = DataType.QWORD, desc = "flags", bigEndian = false, version = {1})
    public Long getFlags() {
        return flags;
    }

    @Field(sort = 30, name = "address", dataType = DataType.QWORD, desc = "address", bigEndian = false, version = {1})
    public Long getAddress() {
        return address;
    }

    @Field(sort = 40, name = "offset", dataType = DataType.QWORD, desc = "offset", bigEndian = false, version = {1})
    public Long getOffset() {
        return offset;
    }

    @Field(sort = 50, name = "size", dataType = DataType.QWORD, desc = "size", bigEndian = false, version = {1})
    public Long getSize() {
        return size;
    }

    @Field(sort = 60, name = "link", dataType = DataType.DWORD, desc = "link", bigEndian = false, version = {1})
    public Integer getLink() {
        return link;
    }

    @Field(sort = 70, name = "info", dataType = DataType.DWORD, desc = "info", bigEndian = false, version = {1})
    public Integer getInfo() {
        return info;
    }

    @Field(sort = 80, name = "addrAlign", dataType = DataType.QWORD, desc = "addrAlign", bigEndian = false, version = {1})
    public Long getAddrAlign() {
        return addrAlign;
    }

    @Field(sort = 90, name = "entrySize", dataType = DataType.QWORD, desc = "entrySize", bigEndian = false, version = {1})
    public Long getEntrySize() {
        return entrySize;
    }

    public JSONObject getHexRelated() {
        JSONObject result = new JSONObject();
        result.put("address", "0x" + Long.toHexString(address));
        result.put("offset", "0x" + Long.toHexString(offset));
        result.put("size", "0x" + Long.toHexString(size));
        result.put("entrySize", "0x" + Long.toHexString(entrySize));
        return result;
    }

    public String toString() {
        return JSON.toJSONString(this);
    }

}

ElfSegment 有多类实现, 这里不一一列举 

ElfNoteSegment

/**
 * ElfInterpSegment
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:31
 */
@Data
@ToString(callSuper = true)
public class ElfNoteSegment extends ElfSegment {

    private Integer nameSize;
    private Integer descSize;
    private Integer type;
    private String nameInNote;
    private Integer[] desc;

}

ElfDynamicSymSegment

/**
 * ElfDynamicSymSegment
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:31
 */
@Data
@ToString(callSuper = true)
public class ElfDynamicSymSegment extends ElfSegment {

    private List<ElfSymTabElement> list;

    @Field(sort = 0, name = "list", dataType = DataType.GENERIC_BEAN_COLLECTION, desc = "list", version = {1})
    public List<ElfSymTabElement> getList() {
        return list;
    }

}


/**
 * ElfSymTabElement
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:31
 */
@Data
public class ElfSymTabElement {

    private String name;
    // 4bytes
    private Integer nameIdx;
    // 1byte, bind + type
    private Integer info;
    // 1byte, 可见属性
    private Integer other;

    // segment idx
    private Integer shNIdx;
    // 8bytes
    private Long value;
    // 8bytes
    private Long size;


    @Field(sort = 0, name = "nameIdx", dataType = DataType.DWORD, desc = "nameIdx", bigEndian = false, version = {1})
    public Integer getNameIdx() {
        return nameIdx;
    }

    @Field(sort = 10, name = "info", dataType = DataType.BYTE, desc = "info", bigEndian = false, version = {1})
    public Integer getInfo() {
        return info;
    }

    @Field(sort = 20, name = "other", dataType = DataType.BYTE, desc = "other", bigEndian = false, version = {1})
    public Integer getOther() {
        return other;
    }

    @Field(sort = 30, name = "shNIdx", dataType = DataType.WORD, desc = "shNIdx", bigEndian = false, version = {1})
    public Integer getShNIdx() {
        return shNIdx;
    }

    @Field(sort = 40, name = "value", dataType = DataType.QWORD, desc = "value", bigEndian = false, version = {1})
    public Long getValue() {
        return value;
    }

    @Field(sort = 50, name = "size", dataType = DataType.QWORD, desc = "size", bigEndian = false, version = {1})
    public Long getSize() {
        return size;
    }

    @Override
    public String toString() {
        JSONObject result = new JSONObject();
        result.put("name", name);
        result.put("info", info);
        result.put("other", other);
        result.put("shNIdx", shNIdx);
        result.put("value", Long.toHexString(value));
        result.put("size", size);
        return result.toString();
    }
}

相关实体的编码解码如下 

ElfFileCodec

/**
 * ElfFileCodec
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 10:23
 */
public class ElfFileCodec extends AbstractCodec<ElfFile, ElfFile> {

    private AbstractCodec<ElfHeader, ElfHeader> headerCodec = CodecUtils.createCodecForClazz(ElfHeader.class, 1);
    private AbstractCodec<ElfProgramHeader, ElfProgramHeader> phHeaderCodec = CodecUtils.createCodecForClazz(ElfProgramHeader.class, 1);
    private AbstractCodec<ElfSectionHeader, ElfSectionHeader> sectionHeaderCodec = CodecUtils.createCodecForClazz(ElfSectionHeader.class, 1);
    private ElfSegmentCodec segmentCodec = new ElfSegmentCodec();

    @Override
    public void encode(ElfFile entity, ByteBuf buf) {

    }

    @Override
    public ElfFile decode(ByteBuf buf) {
        debugCurrentBufReaderIdx(buf, "before elf header codec");
        long offsetInFile = buf.readerIndex();
        ElfHeader header = headerCodec.decode(buf);
        header.setOffsetInFile(offsetInFile);
        debugCurrentBufReaderIdx(buf, "after elf header codec");
        int programNum = header.getPhnum(), sectionNum = header.getShnum();
        int sectionHeaderSz = sectionHeaderCodec.length() * sectionNum;

        debugCurrentBufReaderIdx(buf, "before program header codec");
        List<ElfProgramHeader> programHeaders = new ArrayList<>();
        for (int i = 0; i < programNum; i++) {
            offsetInFile = buf.readerIndex();
            ElfProgramHeader phHeader = phHeaderCodec.decode(buf);
            phHeader.setOffsetInFile(offsetInFile);
            programHeaders.add(phHeader);
        }
        debugCurrentBufReaderIdx(buf, "after program header codec");

        debugCurrentBufReaderIdx(buf, "before sections codec");
        int allRemaining = buf.readableBytes();
        int sectionBytesSz = allRemaining - sectionHeaderSz;
        ByteArrayWithExactlyLenCodec byteArrayCodec = new ByteArrayWithExactlyLenCodec(sectionBytesSz);
        Integer[] sectionBytesInInteger = byteArrayCodec.decode(buf);
        debugCurrentBufReaderIdx(buf, "after sections codec");

        debugCurrentBufReaderIdx(buf, "before section header codec");
        List<ElfSectionHeader> sectionHeaders = new ArrayList<>();
        for (int i = 0; i < sectionNum; i++) {
            sectionHeaders.add(sectionHeaderCodec.decode(buf));
        }
        debugCurrentBufReaderIdx(buf, "after section header codec");

        // section headers
        List<ElfSegment> segments = new ArrayList<>();
        for (ElfSectionHeader secHeader : sectionHeaders) {
            int sectionSize = secHeader.getSize().intValue();
            ByteArrayWithExactlyLenCodec sectionByteArrayCodec = new ByteArrayWithExactlyLenCodec(sectionSize);
            Integer[] sectionBytes = new Integer[]{};
            if (secHeader.getOffset() > 0) {
                buf.readerIndex(secHeader.getOffset().intValue());
                sectionBytes = (sectionByteArrayCodec.decode(buf));
            }

            segmentCodec.setSecHeader(secHeader);
            ElfSegment elfSegment = segmentCodec.decode(Unpooled.wrappedBuffer(transferBytes(sectionBytes)));
            elfSegment.setBytes(sectionBytes);
            elfSegment.setOffsetInFile(secHeader.getOffset());
            segments.add(elfSegment);
        }

        // resolve xx names
        resolveRelatedNames(header, sectionHeaders, segments);

        ElfFile result = new ElfFile();
        result.setHeader(header);
        result.setProgramHeaders(programHeaders);
        result.setSectionBytes(sectionBytesInInteger);
        result.setSegments(segments);
        result.setSectionHeaders(sectionHeaders);
        return result;
    }

    private void resolveRelatedNames(ElfHeader header, List<ElfSectionHeader> sectionHeaders, List<ElfSegment> segments) {
        ElfSegment segStrTab = segments.get(header.getShstrndx());
        // fill segment name
        for (int i = 0; i < segments.size(); i++) {
            ElfSegment segment = segments.get(i);
            ElfSectionHeader secHeader = sectionHeaders.get(i);
            String segName = lookStringInStrTab(segStrTab.getBytes(), secHeader.getName());
            segment.setName(segName);
        }

        ElfDynStrSegment strTab = (ElfDynStrSegment) lookUpSegment(segments, ".strtab");
        ElfDynStrSegment dynStrTab = (ElfDynStrSegment) lookUpSegment(segments, ".dynstr");
        // fill symtab name
        ElfSymTabSegment symTab = (ElfSymTabSegment) lookUpSegment(segments, ".symtab");
        for (int i = 0; i < symTab.getList().size(); i++) {
            ElfSymTabElement symtabEle = symTab.getList().get(i);
            String eleName = lookStringInStrTab(strTab.getBytes(), symtabEle.getNameIdx());
            symtabEle.setName(eleName);
        }

        // fill dynsym name
        ElfDynamicSymSegment dynSymTab = (ElfDynamicSymSegment) lookUpSegment(segments, ".dynsym");
        for (int i = 0; i < dynSymTab.getList().size(); i++) {
            ElfSymTabElement symtabEle = dynSymTab.getList().get(i);
            String eleName = lookStringInStrTab(dynStrTab.getBytes(), symtabEle.getNameIdx());
            symtabEle.setName(eleName);
        }

        // rela.dyn
        ElfRelaSegment relaDynTab = (ElfRelaSegment) lookUpSegment(segments, ".rela.dyn");
        for (int i = 0; i < relaDynTab.getList().size(); i++) {
            ElfRelaElement symtabEle = relaDynTab.getList().get(i);
            String eleName = dynStrTab.getList().get(symtabEle.getNameIdx());
            symtabEle.setName(eleName);
        }

        // rela.plt
        ElfRelaSegment relaPltTab = (ElfRelaSegment) lookUpSegment(segments, ".rela.plt");
        for (int i = 0; i < relaPltTab.getList().size(); i++) {
            ElfRelaElement symtabEle = relaPltTab.getList().get(i);
            String eleName = dynStrTab.getList().get(symtabEle.getNameIdx());
            symtabEle.setName(eleName);
        }

    }

    public static ElfSegment lookUpSegment(List<ElfSegment> segments, String name) {
        for (ElfSegment segment : segments) {
            if (Objects.equals(name, segment.getName())) {
                return segment;
            }
        }
        return null;
    }

    public static byte[] transferBytes(Integer[] bytes) {
        byte[] result = new byte[bytes.length];
        int idx = 0;
        for (Integer b : bytes) {
            result[idx++] = b.byteValue();
        }
        return result;
    }

    public static String formatOffset(Long offset) {
        return String.format("0x00%s", Long.toHexString(offset));
    }

    public static String toString(Integer[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String part = ByteBufUtil.hexDump(
                    new byte[]{bytes[i].byteValue()}
            );
            sb.append(" ");
            sb.append(part);
        }
        return sb.toString();
    }

    public static String toAddress(Integer[] bytes) {
        StringBuilder sb = new StringBuilder();
        sb.append("0x");
        for (int i = bytes.length - 1; i >= 0; i--) {
            String part = ByteBufUtil.hexDump(
                    new byte[]{bytes[i].byteValue()}
            );
            sb.append(" ");
            sb.append(part);
        }
        return sb.toString();
    }

    public static String lookStringInStrTab(Integer[] bytes, int offset) {
        StringBuilder sb = new StringBuilder();
        for (int i = offset; i < bytes.length; i++) {
            if (bytes[i] == 0x00) {
                break;
            }
            sb.append((char) bytes[i].intValue());
        }
        return sb.toString();
    }

    @Override
    public boolean isFixedLength() {
        return false;
    }

    @Override
    public int length() {
        return 0;
    }

    public void debugCurrentBufReaderIdx(ByteBuf buf, String title) {
        System.out.println(title + " -> " + buf.readerIndex() + " - 0x" + Integer.toHexString(buf.readerIndex()));
    }

}

ElfSegment 有多类实现, 这里不一一列举 

ElfNoteSegmentCodec

/**
 * ElfAbiTagSegmentCodec
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:34
 */
public class ElfNoteSegmentCodec extends AbstractCodec<ElfNoteSegment, ElfNoteSegment> {

    private DWordCodec dWordCodec = new DWordCodec(ByteOrder.LITTLE_ENDIAN);
    private CharsetEncodingStringCodec stringCodec = new CharsetEncodingStringCodec(Constants.CHARSET_UTF8);

    @Override
    public void encode(ElfNoteSegment entity, ByteBuf buf) {

    }

    @Override
    public ElfNoteSegment decode(ByteBuf buf) {
        Integer nameSize = dWordCodec.decode(buf);
        Integer descSize = dWordCodec.decode(buf);
        Integer type = dWordCodec.decode(buf);

        CharsetEncodingStringWithFixedLenCodec nameCodec = new CharsetEncodingStringWithFixedLenCodec(nameSize);
        String name = nameCodec.decode(buf);

        ByteArrayWithFixedLenCodec descCodec = new ByteArrayWithFixedLenCodec(descSize);
        Integer[] desc = descCodec.decode(buf);

        ElfNoteSegment result = new ElfNoteSegment();
        result.setNameSize(nameSize);
        result.setDescSize(descSize);
        result.setType(type);
        result.setNameInNote(name);
        result.setDesc(desc);
        return result;
    }

    @Override
    public boolean isFixedLength() {
        return false;
    }

    @Override
    public int length() {
        return 0;
    }
}

ElfDynamicSymSegmentCodec

/**
 * ElfDynamicSymSegmentCodec
 *
 * @author Jerry.X.He
 * @version 1.0
 * @date 2022/9/27 14:34
 */
public class ElfDynamicSymSegmentCodec extends AbstractCodec<ElfDynamicSymSegment, ElfDynamicSymSegment> {

    AbstractCodec<ElfDynamicSymSegment, ElfDynamicSymSegment> codec = CodecUtils.createCodecForClazz(ElfDynamicSymSegment.class, 1);

    @Override
    public void encode(ElfDynamicSymSegment entity, ByteBuf buf) {

    }

    @Override
    public ElfDynamicSymSegment decode(ByteBuf buf) {
        return codec.decode(buf);
    }

    @Override
    public boolean isFixedLength() {
        return false;
    }

    @Override
    public int length() {
        return 0;
    }
}

解析结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/131981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022年度盘点|聚焦运维服务,云智慧的高光时刻

回首2022&#xff0c;从IE 浏览器退役到AIGC 火遍全球&#xff0c;每一次科技的兴衰演进都打破着技术的新边界。与此同时&#xff0c;随着各行业数据规模爆发式地增长&#xff0c;云智慧作为国内全栈智能运维解决方案服务商&#xff0c;企业数字化地加速转型也为其带来了更多的…

Hibernate validator注解及Spring Boot自定义Hibernate Validator注解校验(超级详细)

一 Hibernate validator是什么 验证数据是贯穿整个应用层&#xff08;从表示层到持久层&#xff09;的常见任务。通常在每一层中都需要实现相同的验证逻辑&#xff0c;这样既耗时又容易出错。为了避免这些验证的重复&#xff0c;开发认原经常将验证逻辑直接捆绑到Model域中&…

1.9 基础综合案例|pyechart第三方包

文章目录json数据格式pyecharts模块介绍pyecharts快速入门数据处理这里使用比较经典的pyechart的第三方包。json数据格式 json是一种轻量级的数据交互形式。可以按照json指定的格式去组织和封装数据。或者这么说本质上json就是一个带有特定格式的字符串。 主要功能&#xff1…

【金猿案例展】正官庄——全渠道会员数据治理驱动商业增长

‍珍岛集团案例本项目案例由珍岛集团投递并参与“数据猿年度金猿策划活动——《2022大数据产业年度创新服务企业》榜单/奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业随着商业品牌的全渠道裂变式发展&#xff0c;对DTC直营会员为中心的综合数据运营提出了新的…

【自学Java】Java基本数据类型

Java基本数据类型 Java基本数据类型 Java 基本数据类型如下表&#xff1a; 序号数据类型大小/位可表示的数据范围默认值1long&#xff08;长整数&#xff09;64-9223372036854775808&#xff5e;92233720368547758070L2int&#xff08;整数&#xff09;32-2147483648&#x…

设置 MYSQL 数据库编码为 utf8mb4

utf-8编码可能2个字节、3个字节、4个字节的字符&#xff0c;但是MySQL的utf8编码只支持3字节的数据&#xff0c;而移动端的表情数据是4个字节的字符。如果直接往采用utf-8编码的数据库中插入表情数据&#xff0c;java程序中将报SQL异常&#xff1a; java.sql.SQLException: Inc…

带音频播放的MPlayer播放器在ARM上的移植笔记

前言 mplayer想要播放带音频的视频文件&#xff0c;需要依赖alsa-lib和zlib&#xff0c;所以交叉编译mplayer前还需要先编译alsa-lib和zlib 一、alsa-lib alsa-lib 是 ALSA 提供的一套 Linux 下的 C 语言函数库&#xff0c;需要将 alsa-lib 移植到板卡上&#xff0c;这样基于…

人话解读LGPLv3

大家都知道&#xff1a;你调用了 LGPL的库&#xff0c;你还是可以开发一个闭源程序。这就说明&#xff0c;LGPL比GPL要宽松。但并不像想象的那么简单。一、为什么会有LGPL作为GPL的发明人Stallman&#xff0c;是自由软件的死忠坚定维护者&#xff0c;为什么还允许让别人用了自己…

2022年终总结-2023新年快乐

这是学习笔记的第 2446篇文章新的一年了&#xff0c;还是得总结点东西&#xff0c;本来想盘一下自己买了多少书&#xff0c;做了哪些有意义的事情&#xff0c;想想我还是自己先慢慢盘吧&#xff0c;发不发出来另说&#xff0c;还是希望写点自己的感悟&#xff0c;也希望对大家有…

LabVIEW共享变量

LabVIEW共享变量 创建共享变量 要创建共享变量&#xff0c;必须先打开一个LabVIEW项目。在项目浏览器窗口中&#xff0c;右键单击终端、项目库或项目库中的文件夹&#xff0c;从快捷菜单中选择新建(New) 变量(Variable)&#xff0c;打开共享变量属性(Shared Variable Proper…

dubbo源码实践-SPI扩展

1 概述 SPI的官方文档说明&#xff1a;Dubbo SPI | Apache Dubbo SPI 全称为 Service Provider Interface&#xff0c;是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中&#xff0c;并由服务加载器读取配置文件&#xff0c;加载实现类。这样可以在运行时&…

我的2022总结

博客记录 踏石留印 抓铁有痕 使用csdn写博客&#xff0c;发帖子&#xff0c;帮助网友回答问题。都是实实在在满足了学习&#xff0c;交流的需求 这是我自己使用 CSDN 各种功能记录&#xff1a; 工作方面&#xff1a; 年初参与了公司的一个产品&#xff0c;主要负责串口服务…

Allegro上如何计算阻抗操作指导

Allegro上如何计算阻抗操作指导 Allegro上同样可以快捷的进行阻抗计算,免去了用第三方软件计算的麻烦,以下图为例 具体操作如下 选择X-section在层叠中把每个层的Dielectric Constant填写正确,即板材的Er值

01月份图形化二级打卡试题

活动时间 从2023年 1月1日至1月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; &#xff08;1&#xff09;小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 &#xff08;2&#xff09;小朋友做完题目后&…

阿里云迎来新主帅,张勇将交出怎样的答卷?

‍‍数据智能产业创新服务媒体——聚焦数智 改变商业岁末年尾&#xff0c;回顾过去展望新篇之际&#xff0c;阿里巴巴集团于29日通过两封邮件宣布了组织架构的调整。以“沉稳内敛”著称的张勇&#xff0c;在解决公司问题时&#xff0c;却尽显雷霆手段。敢于作出不完美的决定在…

【算法】静态单链表、双链表、单调栈与单调队列

文章目录1.单链表2.双链表3.单调栈4.单调队列1.单链表 考虑到效率问题&#xff0c;如果每次都去new结点效率比较慢&#xff0c;平时做题时不采用动态:在有严格的时间要求的环境中&#xff0c;不能频繁使用new操作,new的底层涉及内存分配&#xff0c;调用构造函数&#xff0c;指…

2023创业可以做什么项目,适合新手的六个创业项目推荐

大家好&#xff0c;我是蝶衣王的小编 ​2022年已经进入最后一天了&#xff0c;明天就要步入2023年&#xff0c;个人感觉&#xff0c;明年注定是不平凡的一年&#xff0c;疫情解封&#xff0c;经济生产逐渐恢复&#xff0c;明年开始&#xff0c;创业或者做副业的人肯定会越来越…

视频分割很简单,教你方法三分钟搞定视频剪辑

很多朋友不知道怎么分割视频&#xff0c;今天小编就分享怎么在电脑上分割视频的方法&#xff0c;使用媒体梦工厂操作起来不难&#xff0c;新手小白也能轻松学会&#xff0c;一起接着往下看吧。 第一步&#xff0c;开始剪辑之前&#xff0c;小编准备了多段视频用于演示分割效果&…

【金猿案例展】某大型国有银行——智慧金融产业大脑建设

‍拓尔思案例本项目案例由拓尔思投递并参与“数据猿年度金猿策划活动——《2022大数据产业年度创新服务企业》榜单/奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业该银行为提高金融领域产业经济分析能力&#xff0c;建设智慧金融产业大脑&#xff0c;通过投融资…

计算机组成原理【1】

目录 考点1&#xff1a;硬件发展———————————————————————————— 一.计算机硬件的基本组成 1.早期冯诺依曼机 &#xff08;1&#xff09;冯.诺依曼计算机的特点: 2.现代计算机的结构 3.总结图 二.各个硬件的工作原理 1.寄存器MAR,MDR 2.主存…