PGL services: Difference between revisions

From Nintendo Switch Brew
Jump to navigation Jump to search
 
(26 intermediate revisions by 6 users not shown)
Line 1: Line 1:
PGL (Program Loader) is a sysmodule designed for encapsulating all program loading logic.
PGL (Program Launch) is a sysmodule designed for encapsulating all program launching / management logic.
 
The core logic of this sysmodule was previously encapsulated by the ns:dev interface (and the nn.nssrv.ProcessLaunchControlTask thread in particular).


= pgl =
= pgl =
Line 6: Line 8:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || [[#LaunchProgram]]
| 0 || [[#LaunchProgram|LaunchProgram]]
|-
| 1 || [[#TerminateProcess|TerminateProcess]]
|-
| 2 || [[#LaunchProgramFromHost|LaunchProgramFromHost]]
|-
|-
| 1 || [[#TerminateProcess]]
| 4 || [[#GetProgramLaunchPropertyFromHost|GetProgramLaunchPropertyFromHost]]
|-
|-
| 2 || [[#LaunchProgramFromHost]]
| 5 || [[#GetRunningApplicationProcessId|GetRunningApplicationProcessId]]
|-
|-
| 4 || [[#GetHostContentMetaInfo]]
| 6 || [[#BoostSystemMemoryResourceLimit|BoostSystemMemoryResourceLimit]]
|-
|-
| 5 ||  
| 7 || [[#IsRunningProcess|IsRunningProcess]]
|-
|-
| 6 ||  
| 8 || [[#EnableApplicationCrashReport|EnableApplicationCrashReport]]
|-
|-
| 7 ||  
| 9 || [[#IsApplicationCrashReportEnabled|IsApplicationCrashReportEnabled]]
|-
|-
| 8 ||  
| 10 || [[#EnableApplicationAllThreadDumpOnCrash|EnableApplicationAllThreadDumpOnCrash]]
|-
|-
| 9 ||
| 11 || [19.0.0+] GetProcessId
|-
| 12 || [10.0.0-11.0.1] [[#TriggerSnapShotDumper|TriggerSnapShotDumper]]
|-
| 20 || [[#CreateShellEvent|CreateShellEvent]]
|-
| 21 || [11.0.0-11.0.1]
|}
 
== LaunchProgram ==
Takes an input [[NCM_services#ProgramLocation|ProgramLocation]], an input [[Process_Manager_services#LaunchProgramFlags|LaunchProgramFlags]], an input [[#LaunchFlags]] and an input [[Process_Manager_services#ProcessEnvironment|ProcessEnvironment]]. Returns an output u64 '''ProcessId'''.
 
This calls pm:shell->LaunchProgram with the program location and the input launch flags. If jit_debug!enable_jit_debug is true, [[Process_Manager_services#LaunchProgramFlags|NotifyException]] is ORRd into the flags sent to PM.
 
This then creates a new process tracking structure for the new process id and with the pgl launch flags. If an empty process struct is not allocated from the 0x20 slab heap, pgl aborts.
 
If settings::GetDebugModeFlag() returns 1, then LaunchFlags_EnableCrashReportScreenShotForDevelop is used to enable crash report screenshot, otherwise LaunchFlags_EnableCrashReportScreenShotForProduction is used.
 
== TerminateProcess ==
Takes an input u64 '''ProcessId'''. No output.
 
This just calls pm:shell->TerminateProcess with the input process id.
 
== LaunchProgramFromHost ==
Takes an input [[Process_Manager_services#LaunchProgramFlags|LaunchProgramFlags]] and a MapAlias input buffer containing a [[NCM_services#Path|ContentPath]]. Returns an output u64.
 
The content path must be to an ".nsp" file or a ".nspd" folder. "*.nspd/program0.ncd/" is also allowed. The content path must start with "@Host".
 
This calls fs::MountApplicationPackage on the input content path, and reads content meta from "meta0.ncd" or ".cnmt.nca" extension folder/file depending on whether it is a .nspd or .nsp content path.
 
A location resolver for the Host storage is opened, and EraseProgramRedirection is called for the parsed program id. RedierectProgramPath is then called for the program ID to set it to the input content path.
 
This then calls the implementation function for [[#LaunchProgram]] with the input pm launch flags and pgl launch flags = 0. If [[SPL_services#IsDevelopment]] is false, [[Loader_services|Loader]] will abort.
 
== GetProgramLaunchPropertyFromHost ==
Takes a MapAlias input buffer containing a [[NCM_services#Path|ContentPath]]. Returns an output [[#ProgramLaunchProperty]].
 
== GetRunningApplicationProcessId ==
No input. Returns an output u64 '''ProcessId'''.
 
This calls pm:shell->GetApplicationProcessIdForShell, and returns the output process id. Error 0x6E4 is returned when there is no application process.
 
== BoostSystemMemoryResourceLimit ==
Takes an input u64. No output.
 
This uses the u64 as input to pm:shell->BoostSystemMemoryResourceLimit.
 
== IsRunningProcess ==
Takes an input u64 '''ProcessId'''. Returns an output bool (padded to u32).
 
== EnableApplicationCrashReport ==
Takes an input bool (padded to u32). No output.
 
This calls pm:shell->GetApplicationProcessId. If the returned process ID is tracked, this sets or clears bit 1 (value 0x2) in the tracked process's flags.
 
When a process crash event occurs and pgl launches crash report, the second argument is "%d" formatted with the bitwise AND of this bit and bit 0 (value 0x1).
 
LaunchFlags_EnableDetailedCrashReport causes the process to have both of these flags set, otherwise they are both zero.
 
Thus this command is only useful for disabling/toggling detailed crash reports for applications launched with LaunchFlags_EnableDetailedCrashReport, as processes without the launch flag will always send "0" for the creport argument.
 
== IsApplicationCrashReportEnabled ==
No input. Returns an output bool (padded to u32).
 
This returns the value of the bit set or cleared by [[#EnableApplicationCrashReport]].
 
== EnableApplicationAllThreadDumpOnCrash ==
Takes an input bool (padded to u32). No output.
 
This calls pm:shell->GetApplicationProcessId. If the returned process ID is tracked, this sets or clears bit 3 (value 0x8) in the tracked process's flags.
 
Using this command unconditionally sets bit 2 (value 0x4) in the tracked process's flags.
 
When the SnapShotDumper is launched, argument "-log %d" is set to the value of bit 3 if bit 2 is 1. Otherwise, argument "-log %d" is set to the value of the system setting "snap_shot_dump!output_all_log".
 
Thus, this overrides the log option for the current application process from snap_shot_dump!output_all_log with the input value.
 
Previously this functionality was controlled by ns:am2->EnableApplicationAllThreadDumpOnCrash, which is now a wrapper for this function.
 
== TriggerSnapShotDumper ==
Takes an input [[#SnapShotDumpType]] and a MapAlias input buffer. No output.
 
This manually invokes the same function to launch the SnapShotDumper program (0100000000002071) as is called automatically when a process crashes and jit_debug!enable_jit_debug is 1.
 
If the argument is NULL, then the snap shot dumper is launched with argument Format("D %010llu -log %d -dump %d", process_id, log_option, snap_shot_dump_type - 1).
If the argument is not NULL, the snap shot dumper is launched with argument Format("D %010llu \"%s\" -log %d -dump %d", process_id, argument, log_option, snap_shot_dump_type - 1).
 
When invoked automatically, the SnapShotDumpType is SnapShotDumpType_Full if both "snap_shot_dump!full_dump" and "snap_shot_dump!auto_dump" are true, SnapShotDumpType_Auto if only "snap_shot_dump!auto_dump" is 1, and SnapShotDumpType_None otherwise.
 
== CreateShellEvent ==
No input. Returns a [[#ShellEventObserverHolder]].
 
== ShellEventObserverHolder ==
This is "nn::pgl::ShellEventObserverHolder".
 
{| class="wikitable" border="1"
|-
|-
| 10 ||  
! Cmd || Name
|-
|-
| 12 ||
| 0 || [[#GetShellEvent]]
|-
|-
| 20 || [[#GetEventObserver]]
| 1 || [[#GetShellEventInfo]]
|}
|}
== GetShellEvent ==
No input. Returns an output Event handle.
== GetShellEventInfo ==
No input. Returns an output [[#ShellEventInfo]].
This attempts to receive a [[Process_Manager_services#ProcessEventInfo|ProcessEventInfo]] from the observer's message queue.
Every time a process event occurs, pgl receives the event from PM (it does pm:shell->GetProcessEventHandle() during startup and has a thread looping pm:shell->GetProcessEventInfo() to track process events.
PGL sends to all observers' message queues a [[Process_Manager_services#ProcessEventInfo|ProcessEventInfo]] for each event it receives, thus allowing for multiple subscribers to process events.


= LaunchFlags =
= LaunchFlags =
{| class="wikitable" border="1"
|-
! Bit
! Description
|-
| 0
| EnableDetailedCrashReport
|-
| 1
| EnableCrashReportScreenShotForProduction
|-
| 2
| EnableCrashReportScreenShotForDevelop
|}


The LaunchFlags enum looks like this:
= SnapShotDumpType =
 
{| class=wikitable
{| class=wikitable
! Bit || Mask || Name
! Value || Name
|-
| 0 || 1 || LaunchFlags_EnableDetailedCrashReport
|-
|-
| 1 || 2 || LaunchFlags_EnableCrashReportScreenShotForProduction
| 0 || None
|-
|-
| 2 || 4 || LaunchFlags_EnableCrashReportScreenShotForDevelop
| 1 || Auto
|-
|-
| 2 || Full
|}
|}


== ContentMetaInfo ==
= ProgramLaunchProperty =
This is "nn::pgl::ProgramLaunchProperty".
 
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
Line 63: Line 190:
| 0xC  
| 0xC  
| 0x1  
| 0x1  
| ContentType
| [[NCM_services#ContentType|ContentType]]
|-
|-
| 0xD  
| 0xD  
| 0x1  
| 0x1  
| ID Offset
| Offset
|-
| 0xE
| 0x1
| [[NCM_services#ContentMetaType|ContentMetaType]]
|-
|-
| 0xE
| 0xF
| 0x2
| 0x1
| Padding
| Reserved
|}
|}


= ShellEventInfo =
This is "nn::pgl::ShellEventInfo".


== LaunchProgram ==
[[Category:Services]]
Takes a [[NCM_services#ProgramLocation|ProgramLocation]], a u32 [[Process_Manager_services#LaunchFlags]] pm launch_flags, and a u8 [[#LaunchFlags|LaunchFlags]] pgl launch_flags.
 
This calls pm:shell->LaunchProgram with the program location and the input launch flags. If jit_debug!enable_jit_debug is true, LaunchFlags_SignalOnCrash is ORRd into the flags sent to PM.
 
This then creates a new process tracking structure for the new process id and with the pgl launch flags. If an empty process struct is not allocated from the 0x20 slab heap, pgl aborts.
 
If settings::GetDebugModeFlag() returns 1, then LaunchFlags_EnableCrashReportScreenShotForDevelop is used to enable crash report screenshot, otherwise LaunchFlags_EnableCrashReportScreenShotForProduction is used.
 
It returns a u64 process id.
 
== TerminateProcess ==
This just calls pm:shell->TerminateProcess with the input process id.
 
== GetEventObserver ==
No input. Returns an [[#IEventObserver]].
 
== LaunchProgramFromHost ==
 
This takes an input u32 [[Process_Manager_services#LaunchFlags]] pm launch_flags and a MapAlias input buffer "content path".
 
The content path must be to an ".nsp" file or a ".nspd" folder. "*.nspd/program0.ncd/" is also allowed.
 
This calls fs::MountApplicationPackage on the input content path, and reads content meta from "meta0.ncd" or ".cnmt.nca" extension folder/file depending on whether it is a .nspd or .nsp content path.
 
A location resolver for the Host storage is opened, and EraseProgramRedirection is called for the parsed program id.
 
RedierectProgramPath is then called for the program ID to set it to the input content path.
 
This then calls the implementation function for [[#LaunchProgram]] with the input pm launch flags and pgl launch flags = 0.
 
== GetHostContentMetaInfo ==
 
This takes an input MapAlias buffer "content path", and does the same parsing as [[#LaunchProgramFromHost]].
 
Instead of launching the program, it instead returns an 0x10 output [[#ContentMetaInfo]] from the parsed info.
 
== IEventObserver ==
{| class="wikitable" border="1"
|-
! Cmd || Name
|-
| 0 ||
|-
| 1 ||
|}

Latest revision as of 05:16, 30 May 2026

PGL (Program Launch) is a sysmodule designed for encapsulating all program launching / management logic.

The core logic of this sysmodule was previously encapsulated by the ns:dev interface (and the nn.nssrv.ProcessLaunchControlTask thread in particular).

pgl

Cmd Name
0 LaunchProgram
1 TerminateProcess
2 LaunchProgramFromHost
4 GetProgramLaunchPropertyFromHost
5 GetRunningApplicationProcessId
6 BoostSystemMemoryResourceLimit
7 IsRunningProcess
8 EnableApplicationCrashReport
9 IsApplicationCrashReportEnabled
10 EnableApplicationAllThreadDumpOnCrash
11 [19.0.0+] GetProcessId
12 [10.0.0-11.0.1] TriggerSnapShotDumper
20 CreateShellEvent
21 [11.0.0-11.0.1]

LaunchProgram

Takes an input ProgramLocation, an input LaunchProgramFlags, an input #LaunchFlags and an input ProcessEnvironment. Returns an output u64 ProcessId.

This calls pm:shell->LaunchProgram with the program location and the input launch flags. If jit_debug!enable_jit_debug is true, NotifyException is ORRd into the flags sent to PM.

This then creates a new process tracking structure for the new process id and with the pgl launch flags. If an empty process struct is not allocated from the 0x20 slab heap, pgl aborts.

If settings::GetDebugModeFlag() returns 1, then LaunchFlags_EnableCrashReportScreenShotForDevelop is used to enable crash report screenshot, otherwise LaunchFlags_EnableCrashReportScreenShotForProduction is used.

TerminateProcess

Takes an input u64 ProcessId. No output.

This just calls pm:shell->TerminateProcess with the input process id.

LaunchProgramFromHost

Takes an input LaunchProgramFlags and a MapAlias input buffer containing a ContentPath. Returns an output u64.

The content path must be to an ".nsp" file or a ".nspd" folder. "*.nspd/program0.ncd/" is also allowed. The content path must start with "@Host".

This calls fs::MountApplicationPackage on the input content path, and reads content meta from "meta0.ncd" or ".cnmt.nca" extension folder/file depending on whether it is a .nspd or .nsp content path.

A location resolver for the Host storage is opened, and EraseProgramRedirection is called for the parsed program id. RedierectProgramPath is then called for the program ID to set it to the input content path.

This then calls the implementation function for #LaunchProgram with the input pm launch flags and pgl launch flags = 0. If SPL_services#IsDevelopment is false, Loader will abort.

GetProgramLaunchPropertyFromHost

Takes a MapAlias input buffer containing a ContentPath. Returns an output #ProgramLaunchProperty.

GetRunningApplicationProcessId

No input. Returns an output u64 ProcessId.

This calls pm:shell->GetApplicationProcessIdForShell, and returns the output process id. Error 0x6E4 is returned when there is no application process.

BoostSystemMemoryResourceLimit

Takes an input u64. No output.

This uses the u64 as input to pm:shell->BoostSystemMemoryResourceLimit.

IsRunningProcess

Takes an input u64 ProcessId. Returns an output bool (padded to u32).

EnableApplicationCrashReport

Takes an input bool (padded to u32). No output.

This calls pm:shell->GetApplicationProcessId. If the returned process ID is tracked, this sets or clears bit 1 (value 0x2) in the tracked process's flags.

When a process crash event occurs and pgl launches crash report, the second argument is "%d" formatted with the bitwise AND of this bit and bit 0 (value 0x1).

LaunchFlags_EnableDetailedCrashReport causes the process to have both of these flags set, otherwise they are both zero.

Thus this command is only useful for disabling/toggling detailed crash reports for applications launched with LaunchFlags_EnableDetailedCrashReport, as processes without the launch flag will always send "0" for the creport argument.

IsApplicationCrashReportEnabled

No input. Returns an output bool (padded to u32).

This returns the value of the bit set or cleared by #EnableApplicationCrashReport.

EnableApplicationAllThreadDumpOnCrash

Takes an input bool (padded to u32). No output.

This calls pm:shell->GetApplicationProcessId. If the returned process ID is tracked, this sets or clears bit 3 (value 0x8) in the tracked process's flags.

Using this command unconditionally sets bit 2 (value 0x4) in the tracked process's flags.

When the SnapShotDumper is launched, argument "-log %d" is set to the value of bit 3 if bit 2 is 1. Otherwise, argument "-log %d" is set to the value of the system setting "snap_shot_dump!output_all_log".

Thus, this overrides the log option for the current application process from snap_shot_dump!output_all_log with the input value.

Previously this functionality was controlled by ns:am2->EnableApplicationAllThreadDumpOnCrash, which is now a wrapper for this function.

TriggerSnapShotDumper

Takes an input #SnapShotDumpType and a MapAlias input buffer. No output.

This manually invokes the same function to launch the SnapShotDumper program (0100000000002071) as is called automatically when a process crashes and jit_debug!enable_jit_debug is 1.

If the argument is NULL, then the snap shot dumper is launched with argument Format("D %010llu -log %d -dump %d", process_id, log_option, snap_shot_dump_type - 1). If the argument is not NULL, the snap shot dumper is launched with argument Format("D %010llu \"%s\" -log %d -dump %d", process_id, argument, log_option, snap_shot_dump_type - 1).

When invoked automatically, the SnapShotDumpType is SnapShotDumpType_Full if both "snap_shot_dump!full_dump" and "snap_shot_dump!auto_dump" are true, SnapShotDumpType_Auto if only "snap_shot_dump!auto_dump" is 1, and SnapShotDumpType_None otherwise.

CreateShellEvent

No input. Returns a #ShellEventObserverHolder.

ShellEventObserverHolder

This is "nn::pgl::ShellEventObserverHolder".

Cmd Name
0 #GetShellEvent
1 #GetShellEventInfo

GetShellEvent

No input. Returns an output Event handle.

GetShellEventInfo

No input. Returns an output #ShellEventInfo.

This attempts to receive a ProcessEventInfo from the observer's message queue.

Every time a process event occurs, pgl receives the event from PM (it does pm:shell->GetProcessEventHandle() during startup and has a thread looping pm:shell->GetProcessEventInfo() to track process events.

PGL sends to all observers' message queues a ProcessEventInfo for each event it receives, thus allowing for multiple subscribers to process events.

LaunchFlags

Bit Description
0 EnableDetailedCrashReport
1 EnableCrashReportScreenShotForProduction
2 EnableCrashReportScreenShotForDevelop

SnapShotDumpType

Value Name
0 None
1 Auto
2 Full

ProgramLaunchProperty

This is "nn::pgl::ProgramLaunchProperty".

Offset Size Description
0x0 0x8 ProgramId
0x8 0x4 Version
0xC 0x1 ContentType
0xD 0x1 Offset
0xE 0x1 ContentMetaType
0xF 0x1 Reserved

ShellEventInfo

This is "nn::pgl::ShellEventInfo".