4 use crate::endian
::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32}
;
6 use crate::pod
::{bytes_of, WritableBuffer}
;
7 use crate::write
::string
::*;
8 use crate::write
::util
::*;
11 #[derive(Default, Clone, Copy)]
12 struct SectionOffsets
{
14 str_id
: Option
<StringId
>,
17 associative_section
: u16,
20 #[derive(Default, Clone, Copy)]
21 struct SymbolOffsets
{
23 str_id
: Option
<StringId
>,
28 pub(crate) fn coff_section_info(
30 section
: StandardSection
,
31 ) -> (&'
static [u8], &'
static [u8], SectionKind
) {
33 StandardSection
::Text
=> (&[], &b
".text"[..], SectionKind
::Text
),
34 StandardSection
::Data
=> (&[], &b
".data"[..], SectionKind
::Data
),
35 StandardSection
::ReadOnlyData
36 | StandardSection
::ReadOnlyDataWithRel
37 | StandardSection
::ReadOnlyString
=> (&[], &b
".rdata"[..], SectionKind
::ReadOnlyData
),
38 StandardSection
::UninitializedData
=> {
39 (&[], &b
".bss"[..], SectionKind
::UninitializedData
)
41 // TLS sections are data sections with a special name.
42 StandardSection
::Tls
=> (&[], &b
".tls$"[..], SectionKind
::Data
),
43 StandardSection
::UninitializedTls
=> {
44 // Unsupported section.
45 (&[], &[], SectionKind
::UninitializedTls
)
47 StandardSection
::TlsVariables
=> {
48 // Unsupported section.
49 (&[], &[], SectionKind
::TlsVariables
)
51 StandardSection
::Common
=> {
52 // Unsupported section.
53 (&[], &[], SectionKind
::Common
)
58 pub(crate) fn coff_subsection_name(&self, section
: &[u8], value
: &[u8]) -> Vec
<u8> {
59 let mut name
= section
.to_vec();
65 pub(crate) fn coff_fixup_relocation(&mut self, mut relocation
: &mut Relocation
) -> i64 {
66 if relocation
.kind
== RelocationKind
::GotRelative
{
67 // Use a stub symbol for the relocation instead.
68 // This isn't really a GOT, but it's a similar purpose.
69 // TODO: need to handle DLL imports differently?
70 relocation
.kind
= RelocationKind
::Relative
;
71 relocation
.symbol
= self.coff_add_stub_symbol(relocation
.symbol
);
72 } else if relocation
.kind
== RelocationKind
::PltRelative
{
73 // Windows doesn't need a separate relocation type for
74 // references to functions in import libraries.
75 // For convenience, treat this the same as Relative.
76 relocation
.kind
= RelocationKind
::Relative
;
79 let constant
= match self.architecture
{
80 Architecture
::I386
=> match relocation
.kind
{
81 RelocationKind
::Relative
=> {
82 // IMAGE_REL_I386_REL32
85 _
=> relocation
.addend
,
87 Architecture
::X86_64
=> match relocation
.kind
{
88 RelocationKind
::Relative
=> {
89 // IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5
90 if relocation
.addend
<= -4 && relocation
.addend
>= -9 {
96 _
=> relocation
.addend
,
98 _
=> unimplemented
!(),
100 relocation
.addend
-= constant
;
104 fn coff_add_stub_symbol(&mut self, symbol_id
: SymbolId
) -> SymbolId
{
105 if let Some(stub_id
) = self.stub_symbols
.get(&symbol_id
) {
108 let stub_size
= self.architecture
.address_size().unwrap().bytes();
110 let mut name
= b
".rdata$.refptr.".to_vec();
111 name
.extend(&self.symbols
[symbol_id
.0].name
);
112 let section_id
= self.add_section(Vec
::new(), name
, SectionKind
::ReadOnlyData
);
113 let section
= self.section_mut(section_id
);
114 section
.set_data(vec
![0; stub_size
as usize], u64::from(stub_size
));
115 section
.relocations
= vec
![Relocation
{
118 kind
: RelocationKind
::Absolute
,
119 encoding
: RelocationEncoding
::Generic
,
124 let mut name
= b
".refptr.".to_vec();
125 name
.extend(&self.symbol(symbol_id
).name
);
126 let stub_id
= self.add_raw_symbol(Symbol
{
129 size
: u64::from(stub_size
),
130 kind
: SymbolKind
::Data
,
131 scope
: SymbolScope
::Compilation
,
133 section
: SymbolSection
::Section(section_id
),
134 flags
: SymbolFlags
::None
,
136 self.stub_symbols
.insert(symbol_id
, stub_id
);
141 pub(crate) fn coff_write(&self, buffer
: &mut dyn WritableBuffer
) -> Result
<()> {
142 // Calculate offsets of everything, and build strtab.
144 let mut strtab
= StringTable
::default();
147 offset
+= mem
::size_of
::<coff
::ImageFileHeader
>();
150 offset
+= self.sections
.len() * mem
::size_of
::<coff
::ImageSectionHeader
>();
152 // Calculate size of section data and add section strings to strtab.
153 let mut section_offsets
= vec
![SectionOffsets
::default(); self.sections
.len()];
154 for (index
, section
) in self.sections
.iter().enumerate() {
155 if section
.name
.len() > 8 {
156 section_offsets
[index
].str_id
= Some(strtab
.add(§ion
.name
));
159 let len
= section
.data
.len();
161 // TODO: not sure what alignment is required here, but this seems to match LLVM
162 offset
= align(offset
, 4);
163 section_offsets
[index
].offset
= offset
;
166 section_offsets
[index
].offset
= 0;
169 // Calculate size of relocations.
170 let count
= section
.relocations
.len();
172 section_offsets
[index
].reloc_offset
= offset
;
173 offset
+= count
* mem
::size_of
::<coff
::ImageRelocation
>();
178 for comdat
in &self.comdats
{
179 let symbol
= &self.symbols
[comdat
.symbol
.0];
180 let comdat_section
= match symbol
.section
{
181 SymbolSection
::Section(id
) => id
.0,
183 return Err(Error(format
!(
184 "unsupported COMDAT symbol `{}` section {:?}",
185 symbol
.name().unwrap_or(""),
190 section_offsets
[comdat_section
].selection
= match comdat
.kind
{
191 ComdatKind
::NoDuplicates
=> coff
::IMAGE_COMDAT_SELECT_NODUPLICATES
,
192 ComdatKind
::Any
=> coff
::IMAGE_COMDAT_SELECT_ANY
,
193 ComdatKind
::SameSize
=> coff
::IMAGE_COMDAT_SELECT_SAME_SIZE
,
194 ComdatKind
::ExactMatch
=> coff
::IMAGE_COMDAT_SELECT_EXACT_MATCH
,
195 ComdatKind
::Largest
=> coff
::IMAGE_COMDAT_SELECT_LARGEST
,
196 ComdatKind
::Newest
=> coff
::IMAGE_COMDAT_SELECT_NEWEST
,
197 ComdatKind
::Unknown
=> {
198 return Err(Error(format
!(
199 "unsupported COMDAT symbol `{}` kind {:?}",
200 symbol
.name().unwrap_or(""),
205 for id
in &comdat
.sections
{
206 let section
= &self.sections
[id
.0];
207 if section
.symbol
.is_none() {
208 return Err(Error(format
!(
209 "missing symbol for COMDAT section `{}`",
210 section
.name().unwrap_or(""),
213 if id
.0 != comdat_section
{
214 section_offsets
[id
.0].selection
= coff
::IMAGE_COMDAT_SELECT_ASSOCIATIVE
;
215 section_offsets
[id
.0].associative_section
= comdat_section
as u16 + 1;
220 // Calculate size of symbols and add symbol strings to strtab.
221 let mut symbol_offsets
= vec
![SymbolOffsets
::default(); self.symbols
.len()];
222 let mut symtab_count
= 0;
223 for (index
, symbol
) in self.symbols
.iter().enumerate() {
224 symbol_offsets
[index
].index
= symtab_count
;
227 SymbolKind
::File
=> {
228 // Name goes in auxilary symbol records.
229 let aux_count
= (symbol
.name
.len() + coff
::IMAGE_SIZEOF_SYMBOL
- 1)
230 / coff
::IMAGE_SIZEOF_SYMBOL
;
231 symbol_offsets
[index
].aux_count
= aux_count
as u8;
232 symtab_count
+= aux_count
;
233 // Don't add name to strtab.
236 SymbolKind
::Section
=> {
237 symbol_offsets
[index
].aux_count
= 1;
242 if symbol
.name
.len() > 8 {
243 symbol_offsets
[index
].str_id
= Some(strtab
.add(&symbol
.name
));
247 // Calculate size of symtab.
248 let symtab_offset
= offset
;
249 let symtab_len
= symtab_count
* coff
::IMAGE_SIZEOF_SYMBOL
;
250 offset
+= symtab_len
;
252 // Calculate size of strtab.
253 let strtab_offset
= offset
;
254 let mut strtab_data
= Vec
::new();
255 // First 4 bytes of strtab are the length.
256 strtab
.write(4, &mut strtab_data
);
257 let strtab_len
= strtab_data
.len() + 4;
258 offset
+= strtab_len
;
263 .map_err(|_
| Error(String
::from("Cannot allocate buffer")))?
;
265 // Write file header.
266 let header
= coff
::ImageFileHeader
{
269 match self.architecture
{
270 Architecture
::Arm
=> coff
::IMAGE_FILE_MACHINE_ARMNT
,
271 Architecture
::Aarch64
=> coff
::IMAGE_FILE_MACHINE_ARM64
,
272 Architecture
::I386
=> coff
::IMAGE_FILE_MACHINE_I386
,
273 Architecture
::X86_64
=> coff
::IMAGE_FILE_MACHINE_AMD64
,
275 return Err(Error(format
!(
276 "unimplemented architecture {:?}",
282 number_of_sections
: U16
::new(LE
, self.sections
.len() as u16),
283 time_date_stamp
: U32
::default(),
284 pointer_to_symbol_table
: U32
::new(LE
, symtab_offset
as u32),
285 number_of_symbols
: U32
::new(LE
, symtab_count
as u32),
286 size_of_optional_header
: U16
::default(),
287 characteristics
: match self.flags
{
288 FileFlags
::Coff { characteristics }
=> U16
::new(LE
, characteristics
),
292 buffer
.extend(bytes_of(&header
));
294 // Write section headers.
295 for (index
, section
) in self.sections
.iter().enumerate() {
296 let mut characteristics
= match section
.flags
{
299 } => characteristics
,
302 if section_offsets
[index
].selection
!= 0 {
303 characteristics
|= coff
::IMAGE_SCN_LNK_COMDAT
;
305 characteristics
|= match section
.kind
{
306 SectionKind
::Text
=> {
307 coff
::IMAGE_SCN_CNT_CODE
308 | coff
::IMAGE_SCN_MEM_EXECUTE
309 | coff
::IMAGE_SCN_MEM_READ
311 SectionKind
::Data
=> {
312 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
313 | coff
::IMAGE_SCN_MEM_READ
314 | coff
::IMAGE_SCN_MEM_WRITE
316 SectionKind
::UninitializedData
=> {
317 coff
::IMAGE_SCN_CNT_UNINITIALIZED_DATA
318 | coff
::IMAGE_SCN_MEM_READ
319 | coff
::IMAGE_SCN_MEM_WRITE
321 SectionKind
::ReadOnlyData
| SectionKind
::ReadOnlyString
=> {
322 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
| coff
::IMAGE_SCN_MEM_READ
324 SectionKind
::Debug
| SectionKind
::Other
| SectionKind
::OtherString
=> {
325 coff
::IMAGE_SCN_CNT_INITIALIZED_DATA
326 | coff
::IMAGE_SCN_MEM_READ
327 | coff
::IMAGE_SCN_MEM_DISCARDABLE
329 SectionKind
::Linker
=> coff
::IMAGE_SCN_LNK_INFO
| coff
::IMAGE_SCN_LNK_REMOVE
,
332 | SectionKind
::UninitializedTls
333 | SectionKind
::TlsVariables
335 | SectionKind
::Unknown
336 | SectionKind
::Metadata
337 | SectionKind
::Elf(_
) => {
338 return Err(Error(format
!(
339 "unimplemented section `{}` kind {:?}",
340 section
.name().unwrap_or(""),
344 } | match section
.align
{
345 1 => coff
::IMAGE_SCN_ALIGN_1BYTES
,
346 2 => coff
::IMAGE_SCN_ALIGN_2BYTES
,
347 4 => coff
::IMAGE_SCN_ALIGN_4BYTES
,
348 8 => coff
::IMAGE_SCN_ALIGN_8BYTES
,
349 16 => coff
::IMAGE_SCN_ALIGN_16BYTES
,
350 32 => coff
::IMAGE_SCN_ALIGN_32BYTES
,
351 64 => coff
::IMAGE_SCN_ALIGN_64BYTES
,
352 128 => coff
::IMAGE_SCN_ALIGN_128BYTES
,
353 256 => coff
::IMAGE_SCN_ALIGN_256BYTES
,
354 512 => coff
::IMAGE_SCN_ALIGN_512BYTES
,
355 1024 => coff
::IMAGE_SCN_ALIGN_1024BYTES
,
356 2048 => coff
::IMAGE_SCN_ALIGN_2048BYTES
,
357 4096 => coff
::IMAGE_SCN_ALIGN_4096BYTES
,
358 8192 => coff
::IMAGE_SCN_ALIGN_8192BYTES
,
360 return Err(Error(format
!(
361 "unimplemented section `{}` align {}",
362 section
.name().unwrap_or(""),
367 let mut coff_section
= coff
::ImageSectionHeader
{
369 virtual_size
: U32
::default(),
370 virtual_address
: U32
::default(),
371 size_of_raw_data
: U32
::new(LE
, section
.size
as u32),
372 pointer_to_raw_data
: U32
::new(LE
, section_offsets
[index
].offset
as u32),
373 pointer_to_relocations
: U32
::new(LE
, section_offsets
[index
].reloc_offset
as u32),
374 pointer_to_linenumbers
: U32
::default(),
375 number_of_relocations
: U16
::new(LE
, section
.relocations
.len() as u16),
376 number_of_linenumbers
: U16
::default(),
377 characteristics
: U32
::new(LE
, characteristics
),
379 if section
.name
.len() <= 8 {
380 coff_section
.name
[..section
.name
.len()].copy_from_slice(§ion
.name
);
382 let mut str_offset
= strtab
.get_offset(section_offsets
[index
].str_id
.unwrap());
383 if str_offset
<= 9_999_999 {
384 let mut name
= [0; 7];
390 while str_offset
!= 0 {
391 let rem
= (str_offset
% 10) as u8;
393 name
[6 - len
] = b'
0'
+ rem
;
397 coff_section
.name
= [0; 8];
398 coff_section
.name
[0] = b'
/'
;
399 coff_section
.name
[1..][..len
].copy_from_slice(&name
[7 - len
..]);
400 } else if str_offset
as u64 <= 0xf_ffff_ffff {
401 coff_section
.name
[0] = b'
/'
;
402 coff_section
.name
[1] = b'
/'
;
404 let rem
= (str_offset
% 64) as u8;
407 0..=25 => b'A'
+ rem
,
408 26..=51 => b'a'
+ rem
- 26,
409 52..=61 => b'
0'
+ rem
- 52,
414 coff_section
.name
[7 - i
] = c
;
417 return Err(Error(format
!("invalid section name offset {}", str_offset
)));
420 buffer
.extend(bytes_of(&coff_section
));
423 // Write section data and relocations.
424 for (index
, section
) in self.sections
.iter().enumerate() {
425 let len
= section
.data
.len();
427 write_align(buffer
, 4);
428 debug_assert_eq
!(section_offsets
[index
].offset
, buffer
.len());
429 buffer
.extend(section
.data
.as_slice());
432 if !section
.relocations
.is_empty() {
433 debug_assert_eq
!(section_offsets
[index
].reloc_offset
, buffer
.len());
434 for reloc
in §ion
.relocations
{
435 //assert!(reloc.implicit_addend);
436 let typ
= match self.architecture
{
437 Architecture
::I386
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
438 (RelocationKind
::Absolute
, 16, 0) => coff
::IMAGE_REL_I386_DIR16
,
439 (RelocationKind
::Relative
, 16, 0) => coff
::IMAGE_REL_I386_REL16
,
440 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_I386_DIR32
,
441 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_I386_DIR32NB
,
442 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_I386_SECTION
,
443 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_I386_SECREL
,
444 (RelocationKind
::SectionOffset
, 7, 0) => coff
::IMAGE_REL_I386_SECREL7
,
445 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_I386_REL32
,
446 (RelocationKind
::Coff(x
), _
, _
) => x
,
448 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
451 Architecture
::X86_64
=> match (reloc
.kind
, reloc
.size
, reloc
.addend
) {
452 (RelocationKind
::Absolute
, 64, 0) => coff
::IMAGE_REL_AMD64_ADDR64
,
453 (RelocationKind
::Absolute
, 32, 0) => coff
::IMAGE_REL_AMD64_ADDR32
,
454 (RelocationKind
::ImageOffset
, 32, 0) => coff
::IMAGE_REL_AMD64_ADDR32NB
,
455 (RelocationKind
::Relative
, 32, -4) => coff
::IMAGE_REL_AMD64_REL32
,
456 (RelocationKind
::Relative
, 32, -5) => coff
::IMAGE_REL_AMD64_REL32_1
,
457 (RelocationKind
::Relative
, 32, -6) => coff
::IMAGE_REL_AMD64_REL32_2
,
458 (RelocationKind
::Relative
, 32, -7) => coff
::IMAGE_REL_AMD64_REL32_3
,
459 (RelocationKind
::Relative
, 32, -8) => coff
::IMAGE_REL_AMD64_REL32_4
,
460 (RelocationKind
::Relative
, 32, -9) => coff
::IMAGE_REL_AMD64_REL32_5
,
461 (RelocationKind
::SectionIndex
, 16, 0) => coff
::IMAGE_REL_AMD64_SECTION
,
462 (RelocationKind
::SectionOffset
, 32, 0) => coff
::IMAGE_REL_AMD64_SECREL
,
463 (RelocationKind
::SectionOffset
, 7, 0) => coff
::IMAGE_REL_AMD64_SECREL7
,
464 (RelocationKind
::Coff(x
), _
, _
) => x
,
466 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
470 return Err(Error(format
!(
471 "unimplemented architecture {:?}",
476 let coff_relocation
= coff
::ImageRelocation
{
477 virtual_address
: U32Bytes
::new(LE
, reloc
.offset
as u32),
478 symbol_table_index
: U32Bytes
::new(
480 symbol_offsets
[reloc
.symbol
.0].index
as u32,
482 typ
: U16Bytes
::new(LE
, typ
),
484 buffer
.extend(bytes_of(&coff_relocation
));
490 debug_assert_eq
!(symtab_offset
, buffer
.len());
491 for (index
, symbol
) in self.symbols
.iter().enumerate() {
492 let mut name
= &symbol
.name
[..];
493 let section_number
= match symbol
.section
{
494 SymbolSection
::None
=> {
495 debug_assert_eq
!(symbol
.kind
, SymbolKind
::File
);
496 coff
::IMAGE_SYM_DEBUG
498 SymbolSection
::Undefined
=> coff
::IMAGE_SYM_UNDEFINED
,
499 SymbolSection
::Absolute
=> coff
::IMAGE_SYM_ABSOLUTE
,
500 SymbolSection
::Common
=> coff
::IMAGE_SYM_UNDEFINED
,
501 SymbolSection
::Section(id
) => id
.0 as u16 + 1,
503 let typ
= if symbol
.kind
== SymbolKind
::Text
{
504 coff
::IMAGE_SYM_DTYPE_FUNCTION
<< coff
::IMAGE_SYM_DTYPE_SHIFT
506 coff
::IMAGE_SYM_TYPE_NULL
508 let storage_class
= match symbol
.kind
{
509 SymbolKind
::File
=> {
510 // Name goes in auxilary symbol records.
512 coff
::IMAGE_SYM_CLASS_FILE
514 SymbolKind
::Section
=> coff
::IMAGE_SYM_CLASS_STATIC
,
515 SymbolKind
::Label
=> coff
::IMAGE_SYM_CLASS_LABEL
,
516 SymbolKind
::Text
| SymbolKind
::Data
| SymbolKind
::Tls
=> {
517 match symbol
.section
{
518 SymbolSection
::None
=> {
519 return Err(Error(format
!(
520 "missing section for symbol `{}`",
521 symbol
.name().unwrap_or("")
524 SymbolSection
::Undefined
| SymbolSection
::Common
=> {
525 coff
::IMAGE_SYM_CLASS_EXTERNAL
527 SymbolSection
::Absolute
| SymbolSection
::Section(_
) => {
529 // TODO: does this need aux symbol records too?
530 _
if symbol
.weak
=> coff
::IMAGE_SYM_CLASS_WEAK_EXTERNAL
,
531 SymbolScope
::Unknown
=> {
532 return Err(Error(format
!(
533 "unimplemented symbol `{}` scope {:?}",
534 symbol
.name().unwrap_or(""),
538 SymbolScope
::Compilation
=> coff
::IMAGE_SYM_CLASS_STATIC
,
539 SymbolScope
::Linkage
| SymbolScope
::Dynamic
=> {
540 coff
::IMAGE_SYM_CLASS_EXTERNAL
546 SymbolKind
::Unknown
| SymbolKind
::Null
=> {
547 return Err(Error(format
!(
548 "unimplemented symbol `{}` kind {:?}",
549 symbol
.name().unwrap_or(""),
554 let number_of_aux_symbols
= symbol_offsets
[index
].aux_count
;
555 let value
= if symbol
.section
== SymbolSection
::Common
{
560 let mut coff_symbol
= coff
::ImageSymbol
{
562 value
: U32Bytes
::new(LE
, value
),
563 section_number
: U16Bytes
::new(LE
, section_number
as u16),
564 typ
: U16Bytes
::new(LE
, typ
),
566 number_of_aux_symbols
,
569 coff_symbol
.name
[..name
.len()].copy_from_slice(name
);
571 let str_offset
= strtab
.get_offset(symbol_offsets
[index
].str_id
.unwrap());
572 coff_symbol
.name
[4..8].copy_from_slice(&u32::to_le_bytes(str_offset
as u32));
574 buffer
.extend(bytes_of(&coff_symbol
));
576 // Write auxiliary symbols.
578 SymbolKind
::File
=> {
579 let aux_len
= number_of_aux_symbols
as usize * coff
::IMAGE_SIZEOF_SYMBOL
;
580 debug_assert
!(aux_len
>= symbol
.name
.len());
581 let old_len
= buffer
.len();
582 buffer
.extend(&symbol
.name
);
583 buffer
.resize(old_len
+ aux_len
, 0);
585 SymbolKind
::Section
=> {
586 debug_assert_eq
!(number_of_aux_symbols
, 1);
587 let section_index
= symbol
.section
.id().unwrap().0;
588 let section
= &self.sections
[section_index
];
589 let aux
= coff
::ImageAuxSymbolSection
{
590 length
: U32Bytes
::new(LE
, section
.size
as u32),
591 number_of_relocations
: U16Bytes
::new(LE
, section
.relocations
.len() as u16),
592 number_of_linenumbers
: U16Bytes
::default(),
593 check_sum
: U32Bytes
::new(LE
, checksum(section
.data
.as_slice())),
594 number
: U16Bytes
::new(
596 section_offsets
[section_index
].associative_section
,
598 selection
: section_offsets
[section_index
].selection
,
601 high_number
: U16Bytes
::default(),
603 buffer
.extend(bytes_of(&aux
));
606 debug_assert_eq
!(number_of_aux_symbols
, 0);
611 // Write strtab section.
612 debug_assert_eq
!(strtab_offset
, buffer
.len());
613 buffer
.extend(&u32::to_le_bytes(strtab_len
as u32));
614 buffer
.extend(&strtab_data
);
616 debug_assert_eq
!(offset
, buffer
.len());
623 fn checksum(data
: &[u8]) -> u32 {
624 let mut hasher
= crc32fast
::Hasher
::new_with_initial(0xffff_ffff);