diff options
Diffstat (limited to 'rust/examples/dwarf/dwarf_import/src/die_handlers.rs')
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/die_handlers.rs | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/rust/examples/dwarf/dwarf_import/src/die_handlers.rs b/rust/examples/dwarf/dwarf_import/src/die_handlers.rs deleted file mode 100644 index b2d61842..00000000 --- a/rust/examples/dwarf/dwarf_import/src/die_handlers.rs +++ /dev/null @@ -1,394 +0,0 @@ -// Copyright 2021-2024 Vector 35 Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext, TypeUID}; -use crate::{helpers::*, ReaderType}; -use crate::types::get_type; - -use binaryninja::{ - rc::*, - types::{EnumerationBuilder, FunctionParameter, ReferenceType, Type, TypeBuilder}, -}; - -use gimli::Dwarf; -use gimli::{constants, AttributeValue::Encoding, DebuggingInformationEntry, Unit}; - -pub(crate) fn handle_base_type<R: ReaderType>( - dwarf: &Dwarf<R>, - unit: &Unit<R>, - entry: &DebuggingInformationEntry<R>, - debug_info_builder_context: &DebugInfoBuilderContext<R>, -) -> Option<Ref<Type>> { - // All base types have: - // DW_AT_encoding (our concept of type_class) - // DW_AT_byte_size and/or DW_AT_bit_size - // *DW_AT_name - // *DW_AT_endianity (assumed default for arch) - // *DW_AT_data_bit_offset (assumed 0) - // *Some indication of signedness? - // * = Optional - - let name = debug_info_builder_context.get_name(dwarf, unit, entry)?; - let size = get_size_as_usize(entry)?; - match entry.attr_value(constants::DW_AT_encoding) { - Ok(Some(Encoding(encoding))) => { - match encoding { - constants::DW_ATE_address => None, - constants::DW_ATE_boolean => Some(Type::bool()), - constants::DW_ATE_complex_float => None, - constants::DW_ATE_float => Some(Type::named_float(size, name)), - constants::DW_ATE_signed => Some(Type::named_int(size, true, name)), - constants::DW_ATE_signed_char => Some(Type::named_int(size, true, name)), - constants::DW_ATE_unsigned => Some(Type::named_int(size, false, name)), - constants::DW_ATE_unsigned_char => Some(Type::named_int(size, false, name)), - constants::DW_ATE_imaginary_float => None, - constants::DW_ATE_packed_decimal => None, - constants::DW_ATE_numeric_string => None, - constants::DW_ATE_edited => None, - constants::DW_ATE_signed_fixed => None, - constants::DW_ATE_unsigned_fixed => None, - constants::DW_ATE_decimal_float => Some(Type::named_float(size, name)), - constants::DW_ATE_UTF => Some(Type::named_int(size, false, name)), // TODO : Verify - constants::DW_ATE_UCS => None, - constants::DW_ATE_ASCII => None, // Some sort of array? - constants::DW_ATE_lo_user => None, - constants::DW_ATE_hi_user => None, - _ => None, // Anything else is invalid at time of writing (gimli v0.23.0) - } - } - _ => None, - } -} - -pub(crate) fn handle_enum<R: ReaderType>( - dwarf: &Dwarf<R>, - unit: &Unit<R>, - entry: &DebuggingInformationEntry<R>, - debug_info_builder_context: &DebugInfoBuilderContext<R>, -) -> Option<Ref<Type>> { - // All base types have: - // DW_AT_byte_size - // *DW_AT_name - // *DW_AT_enum_class - // *DW_AT_type - // ?DW_AT_abstract_origin - // ?DW_AT_accessibility - // ?DW_AT_allocated - // ?DW_AT_associated - // ?DW_AT_bit_size - // ?DW_AT_bit_stride - // ?DW_AT_byte_stride - // ?DW_AT_data_location - // ?DW_AT_declaration - // ?DW_AT_description - // ?DW_AT_sibling - // ?DW_AT_signature - // ?DW_AT_specification - // ?DW_AT_start_scope - // ?DW_AT_visibility - // * = Optional - - // Children of enumeration_types are enumerators which contain: - // DW_AT_name - // DW_AT_const_value - // *DW_AT_description - - let enumeration_builder = EnumerationBuilder::new(); - - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); - while let Ok(Some(child)) = children.next() { - if child.entry().tag() == constants::DW_TAG_enumerator { - let name = debug_info_builder_context.get_name(dwarf, unit, child.entry())?; - let attr = &child - .entry() - .attr(constants::DW_AT_const_value) - .unwrap() - .unwrap(); - if let Some(value) = get_attr_as_u64(attr) { - enumeration_builder.insert(name, value); - } else { - log::error!("Unhandled enum member value type - please report this"); - return None; - } - } - } - - let width = match get_size_as_usize(entry).unwrap_or(8) - { - 0 => debug_info_builder_context.default_address_size(), - x => x - }; - - Some(Type::enumeration( - &enumeration_builder.finalize(), - width, - false, - )) -} - -pub(crate) fn handle_typedef( - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, - typedef_name: &String, -) -> (Option<Ref<Type>>, bool) { - // All base types have: - // DW_AT_name - // *DW_AT_type - // * = Optional - - // This will fail in the case where we have a typedef to a type that doesn't exist (failed to parse, incomplete, etc) - if let Some(entry_type_offset) = entry_type { - if let Some(t) = debug_info_builder.get_type(entry_type_offset) { - return (Some(t.get_type()), typedef_name != t.get_name()); - } - } - - // 5.3: "typedef represents a declaration of the type that is not also a definition" - (None, false) -} - -pub(crate) fn handle_pointer<R: ReaderType>( - entry: &DebuggingInformationEntry<R>, - debug_info_builder_context: &DebugInfoBuilderContext<R>, - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, - reference_type: ReferenceType, -) -> Option<Ref<Type>> { - // All pointer types have: - // DW_AT_type - // *DW_AT_byte_size - // ?DW_AT_name - // ?DW_AT_address - // ?DW_AT_allocated - // ?DW_AT_associated - // ?DW_AT_data_location - // * = Optional - - if let Some(pointer_size) = get_size_as_usize(entry) { - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().get_type(); - Some(Type::pointer_of_width( - parent_type.as_ref(), - pointer_size, - false, - false, - Some(reference_type), - )) - } else { - Some(Type::pointer_of_width( - Type::void().as_ref(), - pointer_size, - false, - false, - Some(reference_type), - )) - } - } else if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().get_type(); - Some(Type::pointer_of_width( - parent_type.as_ref(), - debug_info_builder_context.default_address_size(), - false, - false, - Some(reference_type), - )) - } else { - Some(Type::pointer_of_width( - Type::void().as_ref(), - debug_info_builder_context.default_address_size(), - false, - false, - Some(reference_type), - )) - } -} - -pub(crate) fn handle_array<R: ReaderType>( - unit: &Unit<R>, - entry: &DebuggingInformationEntry<R>, - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, -) -> Option<Ref<Type>> { - // All array types have: - // DW_AT_type - // *DW_AT_name - // *DW_AT_ordering - // *DW_AT_byte_stride or DW_AT_bit_stride - // *DW_AT_byte_size or DW_AT_bit_size - // *DW_AT_allocated - // *DW_AT_associated and - // *DW_AT_data_location - // * = Optional - // For multidimensional arrays, DW_TAG_subrange_type or DW_TAG_enumeration_type - - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().get_type(); - - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); - - // TODO : This is currently applying the size in reverse order - let mut result_type: Option<Ref<Type>> = None; - while let Ok(Some(child)) = children.next() { - if let Some(inner_type) = result_type { - result_type = Some(Type::array( - inner_type.as_ref(), - get_subrange_size(child.entry()), - )); - } else { - result_type = Some(Type::array( - parent_type.as_ref(), - get_subrange_size(child.entry()), - )); - } - } - - result_type.map_or(Some(Type::array(parent_type.as_ref(), 0)), Some) - } else { - None - } -} - -pub(crate) fn handle_function<R: ReaderType>( - dwarf: &Dwarf<R>, - unit: &Unit<R>, - entry: &DebuggingInformationEntry<R>, - debug_info_builder_context: &DebugInfoBuilderContext<R>, - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, -) -> Option<Ref<Type>> { - // All subroutine types have: - // *DW_AT_name - // *DW_AT_type (if not provided, void) - // *DW_AT_prototyped - // ?DW_AT_abstract_origin - // ?DW_AT_accessibility - // ?DW_AT_address_class - // ?DW_AT_allocated - // ?DW_AT_associated - // ?DW_AT_data_location - // ?DW_AT_declaration - // ?DW_AT_description - // ?DW_AT_sibling - // ?DW_AT_start_scope - // ?DW_AT_visibility - // * = Optional - - // May have children, including DW_TAG_formal_parameters, which all have: - // *DW_AT_type - // * = Optional - // or is otherwise DW_TAG_unspecified_parameters - - let return_type = match entry_type { - Some(entry_type_offset) => { - debug_info_builder - .get_type(entry_type_offset) - .expect("Subroutine return type was not processed") - .get_type() - } - None => Type::void(), - }; - - // Alias function type in the case that it contains itself - if let Some(name) = debug_info_builder_context.get_name(dwarf, unit, entry) { - debug_info_builder.add_type( - get_uid(dwarf, unit, entry), - &name, - Type::named_type_from_type( - &name, - &Type::function::<&binaryninja::types::Type>(return_type.as_ref(), &[], false), - ), - false, - ); - } - - let mut parameters: Vec<FunctionParameter> = vec![]; - let mut variable_arguments = false; - - // Get all the children and populate - let mut tree = unit.entries_tree(Some(entry.offset())).unwrap(); - let mut children = tree.root().unwrap().children(); - while let Ok(Some(child)) = children.next() { - if child.entry().tag() == constants::DW_TAG_formal_parameter { - if let (Some(child_uid), Some(name)) = { - ( - get_type( - dwarf, - unit, - child.entry(), - debug_info_builder_context, - debug_info_builder, - ), - debug_info_builder_context.get_name(dwarf, unit, child.entry()), - ) - } { - let child_type = debug_info_builder.get_type(child_uid).unwrap().get_type(); - parameters.push(FunctionParameter::new(child_type, name, None)); - } - } else if child.entry().tag() == constants::DW_TAG_unspecified_parameters { - variable_arguments = true; - } - } - - if debug_info_builder_context.get_name(dwarf, unit, entry).is_some() { - debug_info_builder.remove_type(get_uid(dwarf, unit, entry)); - } - - Some(Type::function( - return_type.as_ref(), - ¶meters, - variable_arguments, - )) -} - -pub(crate) fn handle_const( - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, -) -> Option<Ref<Type>> { - // All const types have: - // ?DW_AT_allocated - // ?DW_AT_associated - // ?DW_AT_data_location - // ?DW_AT_name - // ?DW_AT_sibling - // ?DW_AT_type - - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().get_type(); - Some((*parent_type).to_builder().set_const(true).finalize()) - } else { - Some(TypeBuilder::void().set_const(true).finalize()) - } -} - -pub(crate) fn handle_volatile( - debug_info_builder: &mut DebugInfoBuilder, - entry_type: Option<TypeUID>, -) -> Option<Ref<Type>> { - // All const types have: - // ?DW_AT_allocated - // ?DW_AT_associated - // ?DW_AT_data_location - // ?DW_AT_name - // ?DW_AT_sibling - // ?DW_AT_type - - if let Some(entry_type_offset) = entry_type { - let parent_type = debug_info_builder.get_type(entry_type_offset).unwrap().get_type(); - Some((*parent_type).to_builder().set_volatile(true).finalize()) - } else { - Some(TypeBuilder::void().set_volatile(true).finalize()) - } -} |
