From 174473211ad4c164af5fbe1cb0146bf4bbcdff20 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 11 Oct 2024 18:47:35 +0200 Subject: [PATCH] [darwin-framework-tool] Add a memory dump-graph command (#36017) --- examples/darwin-framework-tool/BUILD.gn | 5 ++ .../commands/memory/Commands.h | 32 ++++++++ .../commands/memory/DumpMemoryGraphCommand.h | 42 ++++++++++ .../commands/memory/DumpMemoryGraphCommand.mm | 28 +++++++ .../commands/memory/LeaksTool.h | 24 ++++++ .../commands/memory/LeaksTool.mm | 79 +++++++++++++++++++ examples/darwin-framework-tool/main.mm | 2 + .../Matter.xcodeproj/project.pbxproj | 28 +++++++ 8 files changed, 240 insertions(+) create mode 100644 examples/darwin-framework-tool/commands/memory/Commands.h create mode 100644 examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.h create mode 100644 examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.mm create mode 100644 examples/darwin-framework-tool/commands/memory/LeaksTool.h create mode 100644 examples/darwin-framework-tool/commands/memory/LeaksTool.mm diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index 2c202475a70ea9..5e7b7d641030b8 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -209,6 +209,11 @@ executable("darwin-framework-tool") { "commands/discover/Commands.h", "commands/discover/DiscoverCommissionablesCommand.h", "commands/discover/DiscoverCommissionablesCommand.mm", + "commands/memory/Commands.h", + "commands/memory/DumpMemoryGraphCommand.h", + "commands/memory/DumpMemoryGraphCommand.mm", + "commands/memory/LeaksTool.h", + "commands/memory/LeaksTool.mm", "commands/pairing/Commands.h", "commands/pairing/DeviceControllerDelegateBridge.mm", "commands/pairing/GetCommissionerNodeIdCommand.h", diff --git a/examples/darwin-framework-tool/commands/memory/Commands.h b/examples/darwin-framework-tool/commands/memory/Commands.h new file mode 100644 index 00000000000000..d58d62db1cfe93 --- /dev/null +++ b/examples/darwin-framework-tool/commands/memory/Commands.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include "commands/common/Commands.h" +#include "commands/memory/DumpMemoryGraphCommand.h" + +void registerCommandsMemory(Commands & commands) +{ + const char * clusterName = "memory"; + commands_list clusterCommands = { + make_unique(), + }; + + commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for inspecting program memory."); +} diff --git a/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.h b/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.h new file mode 100644 index 00000000000000..a4eedfe6171ce9 --- /dev/null +++ b/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "../common/CHIPCommandBridge.h" + +#include + +/** + * This command dump the memory graph of the program. + */ + +class DumpMemoryGraphCommand : public CHIPCommandBridge +{ +public: + DumpMemoryGraphCommand() : CHIPCommandBridge("dump-graph") + { + AddArgument("filepath", &mFilePath, + "An optional filepath to save the memory graph to. Defaults to 'darwin-framework-tool.memgraph"); + } + + /////////// CHIPCommandBridge Interface ///////// + CHIP_ERROR RunCommand() override; + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Milliseconds32(0); } + +private: + chip::Optional mFilePath; +}; diff --git a/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.mm b/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.mm new file mode 100644 index 00000000000000..15bb462f4c6554 --- /dev/null +++ b/examples/darwin-framework-tool/commands/memory/DumpMemoryGraphCommand.mm @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "DumpMemoryGraphCommand.h" + +#include "LeaksTool.h" + +CHIP_ERROR DumpMemoryGraphCommand::RunCommand() +{ + auto err = DumpMemoryGraph(mFilePath); + SetCommandExitStatus(err); + return err; +} diff --git a/examples/darwin-framework-tool/commands/memory/LeaksTool.h b/examples/darwin-framework-tool/commands/memory/LeaksTool.h new file mode 100644 index 00000000000000..101b437932b61b --- /dev/null +++ b/examples/darwin-framework-tool/commands/memory/LeaksTool.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include + +CHIP_ERROR DumpMemoryGraph(chip::Optional filePath); +CHIP_ERROR PrintPools(); diff --git a/examples/darwin-framework-tool/commands/memory/LeaksTool.mm b/examples/darwin-framework-tool/commands/memory/LeaksTool.mm new file mode 100644 index 00000000000000..912134e163f956 --- /dev/null +++ b/examples/darwin-framework-tool/commands/memory/LeaksTool.mm @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "LeaksTool.h" + +#import +#include // For getpid() + +constexpr const char * kDefaultOutputGraphPath = "darwin-framework-tool.memgraph"; + +@interface LeaksTool : NSObject +- (BOOL)runWithArguments:(NSArray * _Nullable)arguments; +@end + +@implementation LeaksTool + +- (BOOL)runWithArguments:(NSArray * _Nullable)arguments +{ + pid_t pid = getpid(); + __auto_type * pidString = [NSString stringWithFormat:@"%d", pid]; + + __auto_type * task = [[NSTask alloc] init]; + task.launchPath = @"/usr/bin/leaks"; + task.arguments = @[ pidString ]; + if (arguments) { + task.arguments = [task.arguments arrayByAddingObjectsFromArray:arguments]; + } + + __auto_type * pipe = [NSPipe pipe]; + task.standardOutput = pipe; + task.standardError = pipe; + + __auto_type * fileHandle = [pipe fileHandleForReading]; + [task launch]; + [task waitUntilExit]; + + int exitCode = [task terminationStatus]; + if (exitCode != EXIT_SUCCESS) { + return NO; + } + + __auto_type * data = [fileHandle readDataToEndOfFile]; + __auto_type * output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSLog(@"%@", output); + + return YES; +} + +@end + +CHIP_ERROR DumpMemoryGraph(chip::Optional filePath) +{ + NSMutableString * outputGraphArgument = [NSMutableString stringWithFormat:@"--outputGraph=%s", kDefaultOutputGraphPath]; + if (filePath.HasValue()) { + outputGraphArgument = [NSMutableString stringWithFormat:@"--outputGraph=%s", filePath.Value()]; + } + + __auto_type * leaksTool = [[LeaksTool alloc] init]; + if (![leaksTool runWithArguments:@[ outputGraphArgument ]]) { + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} diff --git a/examples/darwin-framework-tool/main.mm b/examples/darwin-framework-tool/main.mm index ad31cfe32ee1cc..e0c6e94224ebec 100644 --- a/examples/darwin-framework-tool/main.mm +++ b/examples/darwin-framework-tool/main.mm @@ -27,6 +27,7 @@ #include "commands/delay/Commands.h" #include "commands/discover/Commands.h" #include "commands/interactive/Commands.h" +#include "commands/memory/Commands.h" #include "commands/pairing/Commands.h" #include "commands/payload/Commands.h" #include "commands/provider/Commands.h" @@ -46,6 +47,7 @@ int main(int argc, const char * argv[]) registerCommandsDelay(commands); registerCommandsDiscover(commands); registerCommandsInteractive(commands); + registerCommandsMemory(commands); registerCommandsPayload(commands); registerClusterOtaSoftwareUpdateProviderInteractive(commands); registerCommandsStorage(commands); diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 8a39c63440f9ab..488bd32967453e 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -329,6 +329,11 @@ B2E0D7B7245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2E0D7AE245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm */; }; B2E0D7B8245B0B5C003C5B48 /* MTRSetupPayload.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E0D7AF245B0B5C003C5B48 /* MTRSetupPayload.h */; settings = {ATTRIBUTES = (Public, ); }; }; B2E0D7B9245B0B5C003C5B48 /* MTRSetupPayload.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2E0D7B0245B0B5C003C5B48 /* MTRSetupPayload.mm */; }; + B43B39EA2CB859A5006AA284 /* DumpMemoryGraphCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */; }; + B43B39EB2CB859A5006AA284 /* LeaksTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39E82CB859A5006AA284 /* LeaksTool.mm */; }; + B43B39EC2CB859A5006AA284 /* DumpMemoryGraphCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */; }; + B43B39ED2CB859A5006AA284 /* Commands.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E42CB859A5006AA284 /* Commands.h */; }; + B43B39EE2CB859A5006AA284 /* LeaksTool.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E72CB859A5006AA284 /* LeaksTool.h */; }; B45373AA2A9FE73400807602 /* WebSocketServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B45373A92A9FE73400807602 /* WebSocketServer.cpp */; }; B45373BD2A9FEA9100807602 /* service.c in Sources */ = {isa = PBXBuildFile; fileRef = B45373B22A9FEA9000807602 /* service.c */; settings = {COMPILER_FLAGS = "-Wno-error -Wno-unreachable-code -Wno-conversion -Wno-format-nonliteral"; }; }; B45373BE2A9FEA9100807602 /* network.c in Sources */ = {isa = PBXBuildFile; fileRef = B45373B32A9FEA9000807602 /* network.c */; settings = {COMPILER_FLAGS = "-Wno-error -Wno-unreachable-code -Wno-conversion -Wno-format-nonliteral"; }; }; @@ -775,6 +780,11 @@ B2E0D7AE245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRQRCodeSetupPayloadParser.mm; sourceTree = ""; }; B2E0D7AF245B0B5C003C5B48 /* MTRSetupPayload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRSetupPayload.h; sourceTree = ""; }; B2E0D7B0245B0B5C003C5B48 /* MTRSetupPayload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRSetupPayload.mm; sourceTree = ""; }; + B43B39E42CB859A5006AA284 /* Commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Commands.h; sourceTree = ""; }; + B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DumpMemoryGraphCommand.h; sourceTree = ""; }; + B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DumpMemoryGraphCommand.mm; sourceTree = ""; }; + B43B39E72CB859A5006AA284 /* LeaksTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LeaksTool.h; sourceTree = ""; }; + B43B39E82CB859A5006AA284 /* LeaksTool.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LeaksTool.mm; sourceTree = ""; }; B45373A92A9FE73400807602 /* WebSocketServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSocketServer.cpp; sourceTree = ""; }; B45373B22A9FEA9000807602 /* service.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = service.c; path = "repo/lib/core-net/service.c"; sourceTree = ""; }; B45373B32A9FEA9000807602 /* network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = network.c; path = "repo/lib/core-net/network.c"; sourceTree = ""; }; @@ -897,6 +907,7 @@ 037C3D7B2991BD4F00B7EEE2 /* commands */ = { isa = PBXGroup; children = ( + B43B39E92CB859A5006AA284 /* memory */, 5124311D2BA0C09A000BC136 /* configuration */, B4FCD56C2B603A6300832859 /* bdx */, B4E262182AA0CFFE00DBA5BC /* delay */, @@ -1484,6 +1495,18 @@ path = CHIPTests; sourceTree = ""; }; + B43B39E92CB859A5006AA284 /* memory */ = { + isa = PBXGroup; + children = ( + B43B39E42CB859A5006AA284 /* Commands.h */, + B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */, + B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */, + B43B39E72CB859A5006AA284 /* LeaksTool.h */, + B43B39E82CB859A5006AA284 /* LeaksTool.mm */, + ); + path = memory; + sourceTree = ""; + }; B45373AD2A9FE9BF00807602 /* libwebsockets */ = { isa = PBXGroup; children = ( @@ -1619,6 +1642,9 @@ 037C3DD12991BD5200B7EEE2 /* Commands.h in Headers */, 037C3DB92991BD5000B7EEE2 /* ReportCommandBridge.h in Headers */, 037C3DBE2991BD5000B7EEE2 /* OTASoftwareUpdateInteractive.h in Headers */, + B43B39EC2CB859A5006AA284 /* DumpMemoryGraphCommand.h in Headers */, + B43B39ED2CB859A5006AA284 /* Commands.h in Headers */, + B43B39EE2CB859A5006AA284 /* LeaksTool.h in Headers */, 037C3DBD2991BD5000B7EEE2 /* OTAProviderDelegate.h in Headers */, B4FCD5702B603A6300832859 /* Commands.h in Headers */, 037C3DB02991BD4F00B7EEE2 /* Commands.h in Headers */, @@ -1945,6 +1971,8 @@ B45373DF2A9FEB6F00807602 /* system.c in Sources */, B45373FC2A9FEC4F00807602 /* unix-caps.c in Sources */, B45373FE2A9FEC4F00807602 /* unix-fds.c in Sources */, + B43B39EA2CB859A5006AA284 /* DumpMemoryGraphCommand.mm in Sources */, + B43B39EB2CB859A5006AA284 /* LeaksTool.mm in Sources */, B45374002A9FEC4F00807602 /* unix-init.c in Sources */, B45373FF2A9FEC4F00807602 /* unix-misc.c in Sources */, E04AC67E2BEEA17F00BA409B /* ember-io-storage.cpp in Sources */,