| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1 | //===-- SymbolFileSymtab.cpp ------------------------------------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | #include "SymbolFileSymtab.h" | 
|  | 11 | #include "lldb/Core/Module.h" | 
|  | 12 | #include "lldb/Core/PluginManager.h" | 
|  | 13 | #include "lldb/Core/RegularExpression.h" | 
|  | 14 | #include "lldb/Core/Timer.h" | 
| Greg Clayton | 1f74607 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 15 | #include "lldb/Symbol/CompileUnit.h" | 
|  | 16 | #include "lldb/Symbol/Function.h" | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 17 | #include "lldb/Symbol/ObjectFile.h" | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 18 | #include "lldb/Symbol/ObjectFile.h" | 
|  | 19 | #include "lldb/Symbol/Symbol.h" | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 20 | #include "lldb/Symbol/SymbolContext.h" | 
| Greg Clayton | 1f74607 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 21 | #include "lldb/Symbol/Symtab.h" | 
|  | 22 | #include "lldb/Symbol/TypeList.h" | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 23 |  | 
|  | 24 | using namespace lldb; | 
|  | 25 | using namespace lldb_private; | 
|  | 26 |  | 
|  | 27 | void | 
|  | 28 | SymbolFileSymtab::Initialize() | 
|  | 29 | { | 
|  | 30 | PluginManager::RegisterPlugin (GetPluginNameStatic(), | 
|  | 31 | GetPluginDescriptionStatic(), | 
|  | 32 | CreateInstance); | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | void | 
|  | 36 | SymbolFileSymtab::Terminate() | 
|  | 37 | { | 
|  | 38 | PluginManager::UnregisterPlugin (CreateInstance); | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 |  | 
| Greg Clayton | 57abc5d | 2013-05-10 21:47:16 +0000 | [diff] [blame] | 42 | lldb_private::ConstString | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 43 | SymbolFileSymtab::GetPluginNameStatic() | 
|  | 44 | { | 
| Greg Clayton | 57abc5d | 2013-05-10 21:47:16 +0000 | [diff] [blame] | 45 | static ConstString g_name("symtab"); | 
|  | 46 | return g_name; | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 47 | } | 
|  | 48 |  | 
|  | 49 | const char * | 
|  | 50 | SymbolFileSymtab::GetPluginDescriptionStatic() | 
|  | 51 | { | 
|  | 52 | return "Reads debug symbols from an object file's symbol table."; | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 |  | 
|  | 56 | SymbolFile* | 
|  | 57 | SymbolFileSymtab::CreateInstance (ObjectFile* obj_file) | 
|  | 58 | { | 
|  | 59 | return new SymbolFileSymtab(obj_file); | 
|  | 60 | } | 
|  | 61 |  | 
| Greg Clayton | f02500c | 2013-06-18 22:51:05 +0000 | [diff] [blame] | 62 | size_t | 
|  | 63 | SymbolFileSymtab::GetTypes (SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list) | 
|  | 64 | { | 
|  | 65 | return 0; | 
|  | 66 | } | 
|  | 67 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 68 | SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) : | 
|  | 69 | SymbolFile(obj_file), | 
|  | 70 | m_source_indexes(), | 
|  | 71 | m_func_indexes(), | 
|  | 72 | m_code_indexes(), | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 73 | m_objc_class_name_to_index () | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 74 | { | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | SymbolFileSymtab::~SymbolFileSymtab() | 
|  | 78 | { | 
|  | 79 | } | 
|  | 80 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 81 | uint32_t | 
| Sean Callanan | bfaf54d | 2011-12-03 04:38:43 +0000 | [diff] [blame] | 82 | SymbolFileSymtab::CalculateAbilities () | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 83 | { | 
|  | 84 | uint32_t abilities = 0; | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 85 | if (m_obj_file) | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 86 | { | 
| Greg Clayton | 3046e66 | 2013-07-10 01:23:25 +0000 | [diff] [blame] | 87 | const Symtab *symtab = m_obj_file->GetSymtab(); | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 88 | if (symtab) | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 89 | { | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 90 | //---------------------------------------------------------------------- | 
|  | 91 | // The snippet of code below will get the indexes the module symbol | 
|  | 92 | // table entries that are code, data, or function related (debug info), | 
|  | 93 | // sort them by value (address) and dump the sorted symbols. | 
|  | 94 | //---------------------------------------------------------------------- | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 95 | if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes)) | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 96 | { | 
|  | 97 | abilities |= CompileUnits; | 
|  | 98 | } | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 99 |  | 
|  | 100 | if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, m_func_indexes)) | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 101 | { | 
|  | 102 | symtab->SortSymbolIndexesByValue(m_func_indexes, true); | 
|  | 103 | abilities |= Functions; | 
|  | 104 | } | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 105 |  | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 106 | if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes)) | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 107 | { | 
|  | 108 | symtab->SortSymbolIndexesByValue(m_code_indexes, true); | 
| Tamas Berghammer | d00438e | 2015-07-30 12:38:18 +0000 | [diff] [blame] | 109 | abilities |= Functions; | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 110 | } | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 111 |  | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 112 | if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes)) | 
| Greg Clayton | 5861d3e | 2011-06-19 04:02:02 +0000 | [diff] [blame] | 113 | { | 
|  | 114 | symtab->SortSymbolIndexesByValue(m_data_indexes, true); | 
|  | 115 | abilities |= GlobalVariables; | 
|  | 116 | } | 
| Sean Callanan | 09ab4b7 | 2011-11-30 22:11:59 +0000 | [diff] [blame] | 117 |  | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 118 | lldb_private::Symtab::IndexCollection objc_class_indexes; | 
|  | 119 | if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes)) | 
| Sean Callanan | 09ab4b7 | 2011-11-30 22:11:59 +0000 | [diff] [blame] | 120 | { | 
| Greg Clayton | 1075aca | 2011-12-03 20:02:42 +0000 | [diff] [blame] | 121 | symtab->AppendSymbolNamesToMap (objc_class_indexes, | 
|  | 122 | true, | 
|  | 123 | true, | 
|  | 124 | m_objc_class_name_to_index); | 
|  | 125 | m_objc_class_name_to_index.Sort(); | 
| Sean Callanan | 09ab4b7 | 2011-11-30 22:11:59 +0000 | [diff] [blame] | 126 | } | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 127 | } | 
|  | 128 | } | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 129 | return abilities; | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | uint32_t | 
|  | 133 | SymbolFileSymtab::GetNumCompileUnits() | 
|  | 134 | { | 
|  | 135 | // If we don't have any source file symbols we will just have one compile unit for | 
|  | 136 | // the entire object file | 
|  | 137 | if (m_source_indexes.empty()) | 
| Jim Ingham | 969795f | 2011-09-21 01:17:13 +0000 | [diff] [blame] | 138 | return 0; | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 139 |  | 
| Bruce Mitchener | aaa0ba3 | 2014-07-08 18:05:41 +0000 | [diff] [blame] | 140 | // If we have any source file symbols we will logically organize the object symbols | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 141 | // using these. | 
|  | 142 | return m_source_indexes.size(); | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | CompUnitSP | 
|  | 146 | SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) | 
|  | 147 | { | 
|  | 148 | CompUnitSP cu_sp; | 
|  | 149 |  | 
|  | 150 | // If we don't have any source file symbols we will just have one compile unit for | 
|  | 151 | // the entire object file | 
| Greg Clayton | 9efa076 | 2012-04-26 16:53:42 +0000 | [diff] [blame] | 152 | if (idx < m_source_indexes.size()) | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 153 | { | 
| Greg Clayton | 3046e66 | 2013-07-10 01:23:25 +0000 | [diff] [blame] | 154 | const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 155 | if (cu_symbol) | 
| Jason Molenda | 6ab659a | 2015-07-29 00:42:47 +0000 | [diff] [blame] | 156 | cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false)); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 157 | } | 
|  | 158 | return cu_sp; | 
|  | 159 | } | 
|  | 160 |  | 
| Greg Clayton | 1f74607 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 161 | lldb::LanguageType | 
|  | 162 | SymbolFileSymtab::ParseCompileUnitLanguage (const SymbolContext& sc) | 
|  | 163 | { | 
|  | 164 | return eLanguageTypeUnknown; | 
|  | 165 | } | 
|  | 166 |  | 
|  | 167 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 168 | size_t | 
|  | 169 | SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc) | 
|  | 170 | { | 
|  | 171 | size_t num_added = 0; | 
|  | 172 | // We must at least have a valid compile unit | 
|  | 173 | assert (sc.comp_unit != NULL); | 
| Greg Clayton | 3046e66 | 2013-07-10 01:23:25 +0000 | [diff] [blame] | 174 | const Symtab *symtab = m_obj_file->GetSymtab(); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 175 | const Symbol *curr_symbol = NULL; | 
|  | 176 | const Symbol *next_symbol = NULL; | 
|  | 177 | //  const char *prefix = m_obj_file->SymbolPrefix(); | 
|  | 178 | //  if (prefix == NULL) | 
|  | 179 | //      prefix == ""; | 
|  | 180 | // | 
|  | 181 | //  const uint32_t prefix_len = strlen(prefix); | 
|  | 182 |  | 
|  | 183 | // If we don't have any source file symbols we will just have one compile unit for | 
|  | 184 | // the entire object file | 
|  | 185 | if (m_source_indexes.empty()) | 
|  | 186 | { | 
|  | 187 | // The only time we will have a user ID of zero is when we don't have | 
|  | 188 | // and source file symbols and we declare one compile unit for the | 
|  | 189 | // entire object file | 
|  | 190 | if (!m_func_indexes.empty()) | 
|  | 191 | { | 
|  | 192 |  | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | if (!m_code_indexes.empty()) | 
|  | 196 | { | 
|  | 197 | //          StreamFile s(stdout); | 
|  | 198 | //          symtab->Dump(&s, m_code_indexes); | 
|  | 199 |  | 
|  | 200 | uint32_t idx = 0;   // Index into the indexes | 
|  | 201 | const uint32_t num_indexes = m_code_indexes.size(); | 
|  | 202 | for (idx = 0; idx < num_indexes; ++idx) | 
|  | 203 | { | 
|  | 204 | uint32_t symbol_idx = m_code_indexes[idx]; | 
|  | 205 | curr_symbol = symtab->SymbolAtIndex(symbol_idx); | 
|  | 206 | if (curr_symbol) | 
|  | 207 | { | 
|  | 208 | // Union of all ranges in the function DIE (if the function is discontiguous) | 
| Greg Clayton | e761213 | 2012-03-07 21:03:09 +0000 | [diff] [blame] | 209 | AddressRange func_range(curr_symbol->GetAddress(), 0); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 210 | if (func_range.GetBaseAddress().IsSectionOffset()) | 
|  | 211 | { | 
|  | 212 | uint32_t symbol_size = curr_symbol->GetByteSize(); | 
|  | 213 | if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling()) | 
|  | 214 | func_range.SetByteSize(symbol_size); | 
|  | 215 | else if (idx + 1 < num_indexes) | 
|  | 216 | { | 
|  | 217 | next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]); | 
|  | 218 | if (next_symbol) | 
|  | 219 | { | 
| Greg Clayton | 358cf1e | 2015-06-25 21:46:34 +0000 | [diff] [blame] | 220 | func_range.SetByteSize(next_symbol->GetAddressRef().GetOffset() - curr_symbol->GetAddressRef().GetOffset()); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 221 | } | 
|  | 222 | } | 
|  | 223 |  | 
|  | 224 | FunctionSP func_sp(new Function(sc.comp_unit, | 
|  | 225 | symbol_idx,                 // UserID is the DIE offset | 
|  | 226 | LLDB_INVALID_UID,           // We don't have any type info for this function | 
|  | 227 | curr_symbol->GetMangled(),  // Linker/mangled name | 
|  | 228 | NULL,                       // no return type for a code symbol... | 
|  | 229 | func_range));               // first address range | 
|  | 230 |  | 
|  | 231 | if (func_sp.get() != NULL) | 
|  | 232 | { | 
|  | 233 | sc.comp_unit->AddFunction(func_sp); | 
|  | 234 | ++num_added; | 
|  | 235 | } | 
|  | 236 | } | 
|  | 237 | } | 
|  | 238 | } | 
|  | 239 |  | 
|  | 240 | } | 
|  | 241 | } | 
|  | 242 | else | 
|  | 243 | { | 
|  | 244 | // We assume we | 
|  | 245 | } | 
|  | 246 | return num_added; | 
|  | 247 | } | 
|  | 248 |  | 
|  | 249 | bool | 
|  | 250 | SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc) | 
|  | 251 | { | 
|  | 252 | return false; | 
|  | 253 | } | 
|  | 254 |  | 
|  | 255 | bool | 
| Siva Chandra | d8335e9 | 2015-12-16 00:22:08 +0000 | [diff] [blame^] | 256 | SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc) | 
|  | 257 | { | 
|  | 258 | return false; | 
|  | 259 | } | 
|  | 260 |  | 
|  | 261 | bool | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 262 | SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) | 
|  | 263 | { | 
|  | 264 | return false; | 
|  | 265 | } | 
|  | 266 |  | 
| Sean Callanan | f0c5aeb | 2015-04-20 16:31:29 +0000 | [diff] [blame] | 267 | bool | 
|  | 268 | SymbolFileSymtab::ParseImportedModules (const SymbolContext &sc, std::vector<ConstString> &imported_modules) | 
|  | 269 | { | 
|  | 270 | return false; | 
|  | 271 | } | 
|  | 272 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 273 | size_t | 
|  | 274 | SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc) | 
|  | 275 | { | 
|  | 276 | return 0; | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 |  | 
|  | 280 | size_t | 
|  | 281 | SymbolFileSymtab::ParseTypes (const SymbolContext &sc) | 
|  | 282 | { | 
|  | 283 | return 0; | 
|  | 284 | } | 
|  | 285 |  | 
|  | 286 |  | 
|  | 287 | size_t | 
|  | 288 | SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc) | 
|  | 289 | { | 
|  | 290 | return 0; | 
|  | 291 | } | 
|  | 292 |  | 
|  | 293 | Type* | 
|  | 294 | SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) | 
|  | 295 | { | 
|  | 296 | return NULL; | 
|  | 297 | } | 
|  | 298 |  | 
| Greg Clayton | 57ee306 | 2013-07-11 22:46:58 +0000 | [diff] [blame] | 299 | bool | 
| Bruce Mitchener | 3ad353f | 2015-09-24 03:54:50 +0000 | [diff] [blame] | 300 | SymbolFileSymtab::CompleteType (lldb_private::CompilerType& compiler_type) | 
| Greg Clayton | 1be10fc | 2010-09-29 01:12:09 +0000 | [diff] [blame] | 301 | { | 
| Greg Clayton | 57ee306 | 2013-07-11 22:46:58 +0000 | [diff] [blame] | 302 | return false; | 
| Greg Clayton | 1be10fc | 2010-09-29 01:12:09 +0000 | [diff] [blame] | 303 | } | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 304 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 305 | uint32_t | 
|  | 306 | SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) | 
|  | 307 | { | 
| Greg Clayton | 3046e66 | 2013-07-10 01:23:25 +0000 | [diff] [blame] | 308 | if (m_obj_file->GetSymtab() == NULL) | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 309 | return 0; | 
|  | 310 |  | 
|  | 311 | uint32_t resolved_flags = 0; | 
|  | 312 | if (resolve_scope & eSymbolContextSymbol) | 
|  | 313 | { | 
| Greg Clayton | 3046e66 | 2013-07-10 01:23:25 +0000 | [diff] [blame] | 314 | sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 315 | if (sc.symbol) | 
|  | 316 | resolved_flags |= eSymbolContextSymbol; | 
|  | 317 | } | 
|  | 318 | return resolved_flags; | 
|  | 319 | } | 
|  | 320 |  | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 321 | //------------------------------------------------------------------ | 
|  | 322 | // PluginInterface protocol | 
|  | 323 | //------------------------------------------------------------------ | 
| Greg Clayton | 57abc5d | 2013-05-10 21:47:16 +0000 | [diff] [blame] | 324 | lldb_private::ConstString | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 325 | SymbolFileSymtab::GetPluginName() | 
|  | 326 | { | 
| Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 327 | return GetPluginNameStatic(); | 
|  | 328 | } | 
|  | 329 |  | 
|  | 330 | uint32_t | 
|  | 331 | SymbolFileSymtab::GetPluginVersion() | 
|  | 332 | { | 
|  | 333 | return 1; | 
|  | 334 | } |