ms_coff/
section.rs

1//! Image section
2//!
3//! # References
4//! * <https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header>
5
6use bstr::BStr;
7use core::fmt::Debug;
8use core::mem::size_of;
9use static_assertions::const_assert_eq;
10use zerocopy_derive::*;
11
12#[derive(
13    Copy,
14    Clone,
15    Eq,
16    PartialEq,
17    Default,
18    Hash,
19    Ord,
20    PartialOrd,
21    IntoBytes,
22    FromBytes,
23    Immutable,
24    KnownLayout,
25)]
26#[repr(transparent)]
27pub struct SectionCharacteristics(pub u32);
28
29bitflags::bitflags! {
30    impl SectionCharacteristics: u32 {
31        //
32        // Section characteristics.
33        //
34        //      IMAGE_SCN_TYPE_REG                   0x00000000  // Reserved.
35        //      IMAGE_SCN_TYPE_DSECT                 0x00000001  // Reserved.
36        //      IMAGE_SCN_TYPE_NOLOAD                0x00000002  // Reserved.
37        //      IMAGE_SCN_TYPE_GROUP                 0x00000004  // Reserved.
38        const IMAGE_SCN_TYPE_NO_PAD = 8; // obsolete
39        //      IMAGE_SCN_TYPE_COPY                  0x00000010  // Reserved.
40
41        const IMAGE_SCN_CNT_CODE                   = 0x00000020;  // Section contains code.
42        const IMAGE_SCN_CNT_INITIALIZED_DATA       = 0x00000040;  // Section contains initialized data.
43        const IMAGE_SCN_CNT_UNINITIALIZED_DATA     = 0x00000080;  // Section contains uninitialized data.
44
45        const IMAGE_SCN_LNK_OTHER                  = 0x00000100;  // Reserved.
46        const IMAGE_SCN_LNK_INFO                   = 0x00000200;  // Section contains comments or some other type of information.
47        //      IMAGE_SCN_TYPE_OVER                  0x00000400  // Reserved.
48        const IMAGE_SCN_LNK_REMOVE                 = 0x00000800;  // Section contents will not become part of image.
49        const IMAGE_SCN_LNK_COMDAT                 = 0x00001000;  // Section contents comdat.
50        //                                           0x00002000  // Reserved.
51        //      IMAGE_SCN_MEM_PROTECTED - Obsolete   0x00004000
52        const IMAGE_SCN_NO_DEFER_SPEC_EXC          = 0x00004000;  // Reset speculative exceptions handling bits in the TLB entries for this section.
53        const IMAGE_SCN_GPREL                      = 0x00008000;  // Section content can be accessed relative to GP
54        const IMAGE_SCN_MEM_FARDATA                = 0x00008000;
55        //      IMAGE_SCN_MEM_SYSHEAP  - Obsolete    0x00010000
56        const IMAGE_SCN_MEM_PURGEABLE              = 0x00020000;
57        const IMAGE_SCN_MEM_16BIT                  = 0x00020000;
58        const IMAGE_SCN_MEM_LOCKED                 = 0x00040000;
59        const IMAGE_SCN_MEM_PRELOAD                = 0x00080000;
60
61        const IMAGE_SCN_ALIGN_1BYTES               = 0x00100000;  //
62        const IMAGE_SCN_ALIGN_2BYTES               = 0x00200000;  //
63        const IMAGE_SCN_ALIGN_4BYTES               = 0x00300000;  //
64        const IMAGE_SCN_ALIGN_8BYTES               = 0x00400000;  //
65        const IMAGE_SCN_ALIGN_16BYTES              = 0x00500000;  // Default alignment if no others are specified.
66        const IMAGE_SCN_ALIGN_32BYTES              = 0x00600000;  //
67        const IMAGE_SCN_ALIGN_64BYTES              = 0x00700000;  //
68        const IMAGE_SCN_ALIGN_128BYTES             = 0x00800000;  //
69        const IMAGE_SCN_ALIGN_256BYTES             = 0x00900000;  //
70        const IMAGE_SCN_ALIGN_512BYTES             = 0x00A00000;  //
71        const IMAGE_SCN_ALIGN_1024BYTES            = 0x00B00000;  //
72        const IMAGE_SCN_ALIGN_2048BYTES            = 0x00C00000;  //
73        const IMAGE_SCN_ALIGN_4096BYTES            = 0x00D00000;  //
74        const IMAGE_SCN_ALIGN_8192BYTES            = 0x00E00000;  //
75        // Unused                                    0x00F00000
76        const IMAGE_SCN_ALIGN_MASK                 = 0x00F00000;
77
78        const IMAGE_SCN_LNK_NRELOC_OVFL            = 0x01000000;  // Section contains extended relocations.
79        const IMAGE_SCN_MEM_DISCARDABLE            = 0x02000000;  // Section can be discarded.
80        const IMAGE_SCN_MEM_NOT_CACHED             = 0x04000000;  // Section is not cachable.
81        const IMAGE_SCN_MEM_NOT_PAGED              = 0x08000000;  // Section is not pageable.
82        const IMAGE_SCN_MEM_SHARED                 = 0x10000000;  // Section is shareable.
83        const IMAGE_SCN_MEM_EXECUTE                = 0x20000000;  // Section is executable.
84        const IMAGE_SCN_MEM_READ                   = 0x40000000;  // Section is readable.
85        const IMAGE_SCN_MEM_WRITE                  = 0x80000000;  // Section is writeable.
86    }
87}
88
89impl SectionCharacteristics {
90    /// Returns true if this contains `IMAGE_SCN_MEM_READ`
91    pub fn is_read(self) -> bool {
92        self.intersects(Self::IMAGE_SCN_MEM_READ)
93    }
94
95    /// Returns true if this contains `IMAGE_SCN_MEM_WRITE`
96    pub fn is_write(self) -> bool {
97        self.intersects(Self::IMAGE_SCN_MEM_WRITE)
98    }
99
100    /// Returns true if this contains `IMAGE_SCN_MEM_EXECUTE`
101    pub fn is_exec(self) -> bool {
102        self.intersects(Self::IMAGE_SCN_MEM_EXECUTE)
103    }
104}
105
106impl Debug for SectionCharacteristics {
107    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108        write!(f, "[{:08x}", self.0)?;
109
110        write!(f, "]")
111    }
112}
113
114pub const IMAGE_SIZEOF_SHORT_NAME: usize = 8;
115
116#[allow(non_camel_case_types)]
117#[repr(C)]
118#[derive(
119    Clone,
120    Default,
121    Eq,
122    PartialEq,
123    Ord,
124    PartialOrd,
125    Hash,
126    FromBytes,
127    IntoBytes,
128    Immutable,
129    KnownLayout,
130)]
131pub struct IMAGE_SECTION_HEADER {
132    pub name: [u8; IMAGE_SIZEOF_SHORT_NAME],
133    pub physical_address_or_virtual_size: u32,
134    pub virtual_address: u32,
135    pub size_of_raw_data: u32,
136    pub pointer_to_raw_data: u32,
137    pub pointer_to_relocations: u32,
138    pub pointer_to_linenumbers: u32,
139    pub number_of_relocations: u16,
140    pub number_of_linenumbers: u16,
141    pub characteristics: SectionCharacteristics,
142}
143
144impl IMAGE_SECTION_HEADER {
145    pub fn name(&self) -> &BStr {
146        BStr::new(if let Some(i) = self.name.iter().position(|&b| b == 0) {
147            &self.name[..i]
148        } else {
149            &self.name
150        })
151    }
152}
153
154pub const IMAGE_SIZEOF_SECTION_HEADER: usize = 40;
155
156const_assert_eq!(
157    size_of::<IMAGE_SECTION_HEADER>(),
158    IMAGE_SIZEOF_SECTION_HEADER
159);