GDB Debuggging Commands and Advanced Debugging Scenarios
Core GDB Operations
GDB requires executables compiled with debugging symbols using the -g flag during compilation:
gcc -g source.c -o executable
Essential Commands
quit- Terminate debugging sessionlist- Display source code segmentslist 5,10shows lines 5 through 10list file.c:5,10specifies source filelist function_namedisplays code around function
reverse-search pattern- Search backward for string patternrun- Execute program from beginninghelp command- Access documentationbreak- Set breakpointsbreak 15at line numberbreak functionat function entrybreak location if conditionfor conditional breakpoints
watch expression- Halt when expression value changesnext- Execute next statement (treats functions as single steps)step- Enter function calls and execute line-by-line
Conditional Breakpoints
Breakpoints can be configured to trigger only when specific conditions are met:
break function_name if variable > threshold
Multi-process Debugging
Debug child or parent processes selectively:
set follow-fork-mode child
set follow-fork-mode parent
Byte Order Representation
Little Endian Architecture
Stores least significant bytes at lower memory addresses. Common in x86 systems and many ARM processors.
Big Endian Architecture
Places most significant bytes at lower memory addresses. Used in network protocols and some embedded systems.
Detection Method
Union-based approach exploits memory layout:
int check_endianness() {
union {
uint32_t num;
uint8_t byte;
} detector;
detector.num = 1;
return (detector.byte == 1) ? 1 : 0; // Returns 1 for little endian
}
Network communication between different architectures requires byte order conversion. Same-architecture communication typically doesn't require conversion.
Process Scheduling Mechanisms
Primary Algorithms
- First-Come First-Served (FCFS) - Processes executed in arrival order
- Shortest Job First (SJF) - Prioritizes processes with shortest estimated runtime
- Priority Scheduling - Selects highest priority processes
- Round Robin - Allocates fixed time slices cyclically
- Multilevel Feedback Queue - Combines multiple scheduling strategies
Scheduling Characteristics
- Preemptive: Allows forced suspension of running processes
- Non-preemptive: Processes run until completion or blocking
Memory Management Architecture
Physical Memory Hierarchy
Four-tier organization from fastest to slowest:
- Registers
- Cache memory
- Main RAM
- Disk storage
Memory manager tracks usage, allocates resources during process execution, and reclaims memory upon termination.
Virtual Memory System
Each process receives independent virtual address space. Translation between virtual and physical addresses occurs through page tables.
Privilege Levels in Linux
Execution Modes
- Kernel Mode: Full system access with unrestricted instruction execution
- User Mode: Limited access to protected system resources
Transition Triggers
Three mechanisms initiate kernel mode entry:
- System calls (voluntary)
- Exceptions (involuntary)
- Hardware interrupts (involuntary)
Security isolation prevents user programs from executing privileged operations like memory clearing or clock manipulation.
LRU Cache Implementation
Algorithm Purpose
Least Recently Used eviction strategy removes infrequently accessed items from cache.
Data Structure Design
Combines doubly-linked list with hash map for O(1) operations:
class CacheManager {
private:
std::list<std::pair<int, int>> data_chain;
std::unordered_map<int, std::list<std::pair<int, int>>::iterator> index_map;
int max_capacity;
public:
CacheManager(int size) : max_capacity(size) {}
int retrieve(int key) {
if (index_map.find(key) != index_map.end()) {
auto record = *index_map[key];
data_chain.erase(index_map[key]);
index_map.erase(key);
data_chain.push_front(record);
index_map[key] = data_chain.begin();
return record.second;
}
return -1;
}
void insert(int key, int value) {
if (index_map.find(key) != index_map.end()) {
data_chain.erase(index_map[key]);
index_map.erase(key);
} else if (data_chain.size() >= max_capacity) {
auto last_record = data_chain.back();
index_map.erase(last_record.first);
data_chain.pop_back();
}
data_chain.push_front({key, value});
index_map[key] = data_chain.begin();
}
};